diff --git a/.classpath b/.classpath new file mode 100644 index 00000000..b8cf2815 --- /dev/null +++ b/.classpath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index b5e6a76d..00000000 --- a/.gitattributes +++ /dev/null @@ -1,5 +0,0 @@ -# Github language stats file -external/* linguist-vendored -lib/* linguist-vendored -*.css linguist-vendored -*.js linguist-vendored \ No newline at end of file diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index cc2fb2a5..df5faf13 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,2 @@ -# Configuration and dependencies -/hal.conf -/hal.db* -/lib/zutil-* -/recordings/ - -# Runtime files -/screenlog.0* -/OZW_Log.txt - -# Build and Ide files -build -.gradle -.idea \ No newline at end of file +Zutil.jar +/build/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 591c46cd..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "arduino/lib/NexaControl"] - path = arduino/lib/NexaControl - url = https://github.com/dcollin/NexaControl.git diff --git a/.project b/.project new file mode 100644 index 00000000..c932ca6b --- /dev/null +++ b/.project @@ -0,0 +1,31 @@ + + + ZUtil + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + + diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index c82929e5..00000000 --- a/Jenkinsfile +++ /dev/null @@ -1,35 +0,0 @@ -// Jenkinsfile (Pipeline Script) -node { - // Configure environment - env.JAVA_HOME = tool name: 'jdk-11' - env.REPO_URL = "repo.koc.se/hal.git" //scm.getUserRemoteConfigs()[0].getUrl() - env.BUILD_NAME = "BUILD-${env.BUILD_ID}" - - - checkout scm - - stage('Build') { - sh './gradlew clean' - sh './gradlew build' - } - - stage('Test') { - try { - sh './gradlew test' - } finally { - junit testResults: '**/build/test-results/test/*.xml' - } - } - - stage('Package') { - sh './gradlew distZip' - archiveArtifacts artifacts: 'build/distributions/Hal.zip', fingerprint: true - - // Tag artifact - withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'f8e5f6c6-4adb-4ab2-bb5d-1c8535dff491', - usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { - sh "git tag ${env.BUILD_NAME}" - sh "git push 'https://${USERNAME}:${PASSWORD}@${env.REPO_URL}' ${env.BUILD_NAME}" - } - } -} diff --git a/LICENSE.txt b/LICENSE.txt index 1db896c5..468f259e 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,21 +1,21 @@ -The MIT License (MIT) - -Copyright (c) 2016-2025 Daniel Collin, Ziver Koc - -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. +The MIT License (MIT) + +Copyright (c) 2015 Ziver Koc + +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/README.md b/README.md deleted file mode 100644 index 5a054d6b..00000000 --- a/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# Hal - -Hal is a home automation hub with sensor statistics with the functionality to -share that data between friends. It has been developed to be very extensible so future -Sensors and other input devices can be supported. - -Features: -- **Map**, Set up a house map with sensors and events mapped on a floorplan -- **Triggers and Actions**, IFTTT type functionality -- **Power;Challenge**, Sync power or sensor usage between friends to challenge each other to lower the power usage -- **[Google Assistant Integration](plugins/hal-assistant-google/READNME.md)** - -Currently supported devices: -- **Network Scanner**, IP scanner to detect devices on local network -- **NUT**, Linux UPS daemon -- **Tellstick**, Supported devices: - - NexaSelfLearning - - Oregon0x1A2D -- **Raspberry Pi**, GPIO connected sensors -- **[Zigbee](plugins/hal-zigbee/README.md)** - - Temperature Sensors - - Humidity Sensors - - Pressure Sensors - - OnnOff Devices -- **Google Assistant** -- **MQTT Devices** - -Under development (Not ready to be used yet) -- **Z-Wave** - - -The project is currently in alpha state, and as such things will change and break continuously. - -### Screenshots -![Week Graph](screenshot_01.jpg) - -![Home Map](screenshot_02.jpg) - -![Sensor Overview](screenshot_03.jpg) - -![Event Overview](screenshot_04.jpg) - -## Installing - -To run the Hal server you first need to clone the git repository and then run the -gradle command to build and run the server: - -``` -./gradlew run -``` - -Check `hal.conf.example` for available configuration options. -By default, HAL server will be listening to http://localhost:8080. - -## Running the tests - -The current test coverage is greatly lacking, but to run the available JUnit -test-cases run: - -``` -./gradlew test -``` - -## Architecture - -``` - HalAbstractControlerManager - | - | HalAbstractController - | | - | | HalAbstractDevice - | | | - .-----------. .------------. .--------. - | | | | | | - | | | | ----> | Device | - | | | | | | - | | ----> | Controller | '--------' - | | | | .--------. - | | | | | | - | Manager | | | ----> | Device | - | | | | | | - | | '------------' '--------' - | | .------------. .--------. - | | | | | | - | | ----> | Controller | ----> | Device | - | | | | | | - '-----------' '------------' '--------' - -``` - -## Authors - -* **Daniel Collin** -* **Ziver Koc** - - -## License - -This project is licensed under the MIT License - see the -[LICENSE.txt](LICENSE.txt) file for details - -## Acknowledgments - -* Tellstick, for open-sourcing their code diff --git a/Zutil.iml b/Zutil.iml new file mode 100755 index 00000000..0848f64b --- /dev/null +++ b/Zutil.iml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arduino/ArduinoTellstickDuo/ArduinoTellstickDuo.ino b/arduino/ArduinoTellstickDuo/ArduinoTellstickDuo.ino deleted file mode 100644 index 1ee65e23..00000000 --- a/arduino/ArduinoTellstickDuo/ArduinoTellstickDuo.ino +++ /dev/null @@ -1,72 +0,0 @@ -#include "usart.h" -#include "rf.h" -#include "buffer.h" -#include "config.h" - -/* -* Timer2 interrupt in 16kHz. Samples the RF Rx data pin -*/ -ISR(TIMER2_COMPA_vect) { - - if ( !IS_RADIO_RECIEVER_ON() ) { //if no Radio Rx should be performed - return; - } - - uint8_t bit = RX_PIN_READ(); - - //will store "lows" on even buffer addresses and "highs" on odd buffer addresses - if ( ( ((uintptr_t)bufferWriteP) & 0x1 ) != bit ) { //compare the bit and the buffer pointer address. true if one is odd and one is even. - //step the buffer pointer - if ( bufferWriteP+1 > RF_rxBufferEndP ) { - *RF_rxBufferStartP = 1; //reset the next data point before going there - bufferWriteP = RF_rxBufferStartP; - } else { - *(bufferWriteP+1) = 1; //reset the next data point before going there - ++bufferWriteP; - } - } else { - if ( *bufferWriteP < 255 ) { //Do not step the value if it already is 255 (max value) - ++(*bufferWriteP); //step the buffer value - } - } - -};//end timer2 interrupt - - -void setup() { - - Serial.begin(9600); - - setupPins(); - - //setup timer2 interrupt at 16kHz for RF sampling - cli(); //stop interrupts - TCCR2A = 0; // set entire TCCR2A register to 0 - TCCR2B = 0; // same for TCCR2B - TCNT2 = 0; //initialize counter value to 0 - OCR2A = 124; // = ( (16000000Hz) / (16000Hz*8prescaler) ) - 1 (must be <256) - TCCR2A |= (1 << WGM21); // turn on CTC mode - TCCR2B |= (1 << CS21); // Set CS21 bit for 8 prescaler - TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt - sei(); //allow interrupts - - //reset buffer just to be sure - for (uint8_t* p = RF_rxBufferStartP; p <= RF_rxBufferEndP; ++p) { - *p = 0; - } - - Serial.println(F("+V2")); - - ACTIVATE_RADIO_RECEIVER(); - -};//end setup - -void loop() { - - //Receive and execute command over serial - parseSerialForCommand(); - - //Receive signal over air and send it over serial - parseRadioRXBuffer(); - -};//end loop diff --git a/arduino/ArduinoTellstickDuo/archtech.cpp b/arduino/ArduinoTellstickDuo/archtech.cpp deleted file mode 100644 index 491ce88d..00000000 --- a/arduino/ArduinoTellstickDuo/archtech.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "archtech.h" -#include "buffer.h" - -/******************************************************************************* - --ARCHTECH PROTOCOL SPECIFICATION-- - - ----SIGNAL---- -A signal consists of a PREAMBLE, DATA and an POSTAMBLE. -Each signal is sent 4 times in a row to increase the delivery success rate. - - ----PREAMBLE---- -send high for 250 microseconds -send low for 2,500 microseconds - - ----DATA---- -26 bits of transmitter id -1 bit indicating if the on/off bit is targeting a group -1 bit indicating "on" or "off" -4 bits indicating the targeted unit/channel/device -4 bits indicating a absolute dim level (optional) - -Total: 32 or 36 bits depending if absolute dimming is used - -Each real bit in the data field is sent over air as a pair of two inverted bits. - real bit bits over air - 1 = "10" - 0 = "01" - -Over air a "1"(one) is sent as: -send high for 250 microseconds -send low for 1,250 microseconds - -Over air a "0"(zero) is sent as: -send high for 250 microseconds -send low for 250 microseconds - - ----POSTAMBLE---- -send high for 250 microseconds -send low for 10,000 microseconds - -*******************************************************************************/ - -#define ARCHTECH_SHORT_MIN 2 -#define ARCHTECH_SHORT_MAX 7 -#define ARCHTECH_LONG_MIN 17 -#define ARCHTECH_LONG_MAX 27 -#define ARCHTECH_PREAMP_MIN 40 -#define ARCHTECH_PREAMP_MAX 48 - -#define IS_SHORT(b) ( ARCHTECH_SHORT_MIN <= b && b <= ARCHTECH_SHORT_MAX ) -#define IS_LONG(b) ( ARCHTECH_LONG_MIN <= b && b <= ARCHTECH_LONG_MAX ) -#define IS_PREAMP_LONG(b) ( ARCHTECH_PREAMP_MIN <= b && b <= ARCHTECH_PREAMP_MAX ) - -#define IS_ONE(b1,b2,b3,b4) ( IS_SHORT(b1) && IS_LONG(b2) && IS_SHORT(b3) && IS_SHORT(b4) ) -#define IS_ZERO(b1,b2,b3,b4) ( IS_SHORT(b1) && IS_SHORT(b2) && IS_SHORT(b3) && IS_LONG(b4) ) -#define IS_PREAMP(b1,b2) ( IS_SHORT(b1) && IS_PREAMP_LONG(b2) ) - -bool parseArctechSelfLearning(uint8_t* bufStartP, uint8_t* bufEndP) { //start points to a "high" buffer byte, end points to a "low" buffer byte - uint64_t data = 0; - bool dimValuePresent; - uint8_t b1,b2,b3,b4; - - //parse preamp - - b1 = *bufStartP; - stepBufferPointer(&bufStartP); - b2 = *bufStartP; - stepBufferPointer(&bufStartP); - if (!IS_PREAMP(b1, b2)){ - return false; - } - - //parse data - - uint16_t dataBitsInBuffer = (calculateBufferPointerDistance(bufStartP, bufEndP)-2) / 4; //each bit is representd by 4 high/low - if (dataBitsInBuffer == 32) { - dimValuePresent = false; - } else if (dataBitsInBuffer == 36){ - dimValuePresent = true; - } else { - return false; - } - - for (uint8_t i = 0; i < dataBitsInBuffer; ++i) { - b1 = *bufStartP; //no of high - stepBufferPointer(&bufStartP); - b2 = *bufStartP; //no of low - stepBufferPointer(&bufStartP); - b3 = *bufStartP; //no of high - stepBufferPointer(&bufStartP); - b4 = *bufStartP; //no of low - stepBufferPointer(&bufStartP); - - if (IS_ONE(b1,b2,b3,b4)) { //"one" is sent over air - data <<= 1; //shift in a zero - data |= 0x1; //add one - } else if (IS_ZERO(b1,b2,b3,b4)) { //"zero" is sent over air - data <<= 1; //shift in a zero - } else { - return false; - } - - } - - //data parsed - send event over serial - - Serial.print(F("+Wclass:command;protocol:arctech;model:selflearning;data:0x")); - uint8_t hexToSend = (dimValuePresent ? 9 : 8); - for (int8_t i = hexToSend - 1; i >= 0; --i) { - Serial.print( (byte)((data >> (4 * i)) & 0x0F), HEX); - } - Serial.println(F(";")); - - return true; -}; //end parseArctechSelfLearning diff --git a/arduino/ArduinoTellstickDuo/archtech.h b/arduino/ArduinoTellstickDuo/archtech.h deleted file mode 100644 index c35e307b..00000000 --- a/arduino/ArduinoTellstickDuo/archtech.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ARCHTECH_H -#define ARCHTECH_H - -#include "Arduino.h" - -bool parseArctechSelfLearning(uint8_t* bufStartP, uint8_t* bufEndP); - -#endif //ARCHTECH_H \ No newline at end of file diff --git a/arduino/ArduinoTellstickDuo/buffer.cpp b/arduino/ArduinoTellstickDuo/buffer.cpp deleted file mode 100644 index 446a980c..00000000 --- a/arduino/ArduinoTellstickDuo/buffer.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "buffer.h" - -uint8_t RF_rxBuffer[512]; //must have and even number of elements -uint8_t* RF_rxBufferStartP = &RF_rxBuffer[0]; -uint8_t* RF_rxBufferEndP = &RF_rxBuffer[511]; -volatile uint8_t* bufferWriteP = RF_rxBufferStartP; diff --git a/arduino/ArduinoTellstickDuo/buffer.h b/arduino/ArduinoTellstickDuo/buffer.h deleted file mode 100644 index 9cee3b1e..00000000 --- a/arduino/ArduinoTellstickDuo/buffer.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef BUFFER_H -#define BUFFER_H - -#include "Arduino.h" - -extern uint8_t RF_rxBuffer[512]; //must have and even number of elements -extern uint8_t* RF_rxBufferStartP; -extern uint8_t* RF_rxBufferEndP; -extern volatile uint8_t* bufferWriteP; - -inline uint16_t calculateBufferPointerDistance(uint8_t* bufStartP, uint8_t* bufEndP) { - if (bufStartP <= bufEndP) { - return bufEndP - bufStartP + 1; - } else { - return (RF_rxBufferEndP - bufStartP) + (bufEndP - RF_rxBufferStartP) + 2; - } -}; //end calculateBufferPointerDistance - -inline uint8_t* getNextBufferPointer(uint8_t* p) { - if ( p + 1 > RF_rxBufferEndP) { - return RF_rxBufferStartP; - } else { - return p + 1; - } -}; //end getNextBufferPointer - -inline void stepBufferPointer(uint8_t** p) { - *p = getNextBufferPointer(*p); -}; //end stepBufferPointer - -#endif //BUFFER_H diff --git a/arduino/ArduinoTellstickDuo/config.h b/arduino/ArduinoTellstickDuo/config.h deleted file mode 100644 index 1f0c7913..00000000 --- a/arduino/ArduinoTellstickDuo/config.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#include "Arduino.h" - -/* -* RX PIN = 7 -* TX PIN = 8 -*/ -inline void setupPins(){ - pinMode(7, INPUT); - pinMode(8, OUTPUT); -}; - -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) - //pin7 = PD7 = port D, bit 8 - #define RX_PIN_READ() ( digitalRead(7) ) // optimized "digitalRead(7)" - //pin8 = PB0 = port B, bit 1 - #define TX_PIN_LOW() ( PORTB &= 0b01111111 ) // optimized "digitalWrite(8, LOW)" - #define TX_PIN_HIGH() ( PORTB |= 0b10000000 ) // optimized "digitalWrite(8, HIGH)" -#else - #unsupported architecture -#endif - -#endif //CONFIG_H diff --git a/arduino/ArduinoTellstickDuo/oregonV2.1.cpp b/arduino/ArduinoTellstickDuo/oregonV2.1.cpp deleted file mode 100644 index b0319daf..00000000 --- a/arduino/ArduinoTellstickDuo/oregonV2.1.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#include "oregonV2.1.h" -#include "buffer.h" - -/******************************************************************************* - --OREGON v2.1 PROTOCOL SPECIFICATION-- - - ----SIGNAL---- -A signal consists of a PREAMBLE, DATA and an POSTAMBLE. -Each signal is sent 2 times in a row to increase the delivery success rate. -Between the two times there is a "low" pause of 8192us. - - ----PREAMBLE---- -send 16 "1"(ones) over the air - - ----DATA---- -16 bits of sensor type -XX bits of data (where XX <= 64) - -The length XX depends on the sensor type. I.e. 0x1A2D => XX=56 - -Over air a "1"(one) is sent as: -send high for 512 microseconds -send low for 1024 microseconds -send high for 512 microseconds - -Over air a "0"(zero) is sent as: -send low for 512 microseconds -send high for 1024 microseconds -send low for 512 microseconds - - ----POSTAMBLE---- -send 8 "0"(zeros) over the air - -*******************************************************************************/ - -#define SMALL_PULSE(x) ( 4<=x && x<=13 ) -#define BIG_PULSE(x) ( 12<=x && x<=22 ) -#define MORE_DATA_NEEDED -1 -#define INVALID_DATA -2 - -enum { - PARSE_PREAMP = 0, - PARSE_ID, - PARSE_DATA -} static state = PARSE_PREAMP; - -static uint8_t byteCnt = 0; -static uint8_t bitCnt = 0; -static uint8_t totByteCnt = 0; -int8_t byteLength = -1; - -void reset() { - byteCnt = 0; - bitCnt = 0; - totByteCnt = 0; - state = PARSE_PREAMP; - byteLength = -1; -}; //end reset - -void parseOregonStream(bool level, uint8_t count) { - static uint8_t cnt = 0; //used for counting stuff independent in every state - static uint16_t sensorType = 0; - static int8_t byte; - static uint8_t bytesToParse = 0; //the number of bytes left in the data part to parse - static uint8_t buffer[8]; - - if (level) { - count+=3; - } else { - count-=3; - } - - switch(state) { - case PARSE_PREAMP: //look for 25 big pulses followed by one short in a row - if (BIG_PULSE(count)) { - ++cnt; - break; - } - if (SMALL_PULSE(count)) { - if (cnt > 25) { - state=PARSE_ID; - sensorType = 0; - } - cnt = 0; - } - break; - - case PARSE_ID: //get the two first Bytes - byte = getByte(level, count); - if (byte == INVALID_DATA) { - reset(); - cnt = 0; - break; - } else if (byte == MORE_DATA_NEEDED) { - break; - } else { - if (sensorType == 0) { - sensorType = byte << 8; - } else { - sensorType |= byte; - switch (sensorType) { - case 0xEA4C: - bytesToParse = 5; - byteLength = 63; - break; - case 0x0A4D: - case 0x1A2D: //sensor THGR2228N (channel + sensor_id + battery_level + temp + humidity + checksum) - bytesToParse = 7; - byteLength = 79; - break; - default: - reset(); - cnt = 0; - return; - } - state = PARSE_DATA; - cnt = 0; - } - } - break; - - case PARSE_DATA: //get the remaining data - byte = getByte(level, count); - if (byte == INVALID_DATA) { - reset(); - cnt = 0; - break; - } else if (byte == MORE_DATA_NEEDED) { - break; - } - buffer[cnt] = byte; - ++cnt; - if (bytesToParse == 0) { - Serial.print(F("+Wclass:sensor;protocol:oregon;model:0x")); - Serial.print(sensorType, HEX); - Serial.print(F(";data:0x")); - for (int8_t i = 0; i < cnt; ++i) { - Serial.print(buffer[i], HEX); - } - Serial.println(F(";")); - reset(); - cnt = 0; - } - --bytesToParse; - - break; - } - -}; //end parseOregonStream - -int8_t getByte(bool level, uint8_t count) { - int8_t bit = getBit(level, count); - static uint8_t byte = 0; - - if (bit == INVALID_DATA) { - return INVALID_DATA; - } else if (bit == MORE_DATA_NEEDED) { - return MORE_DATA_NEEDED; - } - byte >>= 1; - if (bit) { - byte |= (1<<7); - } - ++totByteCnt; - ++byteCnt; - if (byteCnt < 8) { - return MORE_DATA_NEEDED; - } - byteCnt=0; - return byte; -}; //end getByte - -int8_t getBit(bool level, uint8_t count) { - static bool bit = 0; - - if (bitCnt == 0) { - //First pulse must be small - if (!SMALL_PULSE(count)) { - return INVALID_DATA; - } - bitCnt = 1; - - } else if (bitCnt == 1) { - //Second pulse must be long - if (!BIG_PULSE(count) && totByteCnt!=byteLength){ //special check - last byte might have strange values - bitCnt = 0; - return INVALID_DATA; - } - - bit = level; - bitCnt = 2; - return bit; - - } else if (bitCnt == 2) { - //Prepare for next bit - if (level && SMALL_PULSE(count)) { - //Clean start - bitCnt = 0; - } else if (BIG_PULSE(count)) { - //Combined bit - bitCnt = 1; - } else if (SMALL_PULSE(count)) { - //Clean start - bitCnt = 0; - } - return MORE_DATA_NEEDED; - } - - return MORE_DATA_NEEDED; -}; //end getBit diff --git a/arduino/ArduinoTellstickDuo/oregonV2.1.h b/arduino/ArduinoTellstickDuo/oregonV2.1.h deleted file mode 100644 index 953a94c3..00000000 --- a/arduino/ArduinoTellstickDuo/oregonV2.1.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef OREGONV21_H -#define OREGONV21_H - -#include "Arduino.h" - -void reset(); -void parseOregonStream(bool level, uint8_t sampleCount); -int8_t getByte(bool level, uint8_t count); -int8_t getBit(bool level, uint8_t count); - -#endif //OREGONV21_H \ No newline at end of file diff --git a/arduino/ArduinoTellstickDuo/rf.cpp b/arduino/ArduinoTellstickDuo/rf.cpp deleted file mode 100644 index c97cc0d7..00000000 --- a/arduino/ArduinoTellstickDuo/rf.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include "rf.h" -#include "buffer.h" -#include "archtech.h" -#include "config.h" -#include "oregonV2.1.h" - -#define SILENCE_LENGTH 100 //the number of samples with "low" that represents a silent period between two signals - -volatile bool RFRX = false; - -void parseRadioRXBuffer() { - static uint8_t* bufferReadP = RF_rxBufferStartP; - static uint8_t* startDataP = 0; //will always point to a "high" buffer address - static uint8_t* endDataP = 0; //will always point to a "low" buffer address - static uint8_t prevValue = 0; //contains the value of the previous buffer index read - - bool parse = false; - while (bufferReadP != bufferWriteP) { //stop if the read pointer is pointing to where the writing is currently performed - uint8_t sampleCount = *bufferReadP; - - if ( (((uintptr_t)bufferReadP) & 0x1) == 1 ) { //buffer pointer is odd (stores highs) - //Serial.print("high:"); Serial.println(sampleCount); - if (prevValue >= SILENCE_LENGTH) { - startDataP = bufferReadP; //some new data must start here since this is the first "high" after a silent period - } - - //stream data to stream parsers - parseOregonStream(HIGH, sampleCount); - - } else { //buffer pointer is even (stores lows) - //Serial.print("low:"); Serial.println(sampleCount); - if (sampleCount >= SILENCE_LENGTH) { //evaluate if it is time to parse the curernt data - endDataP = bufferReadP; //this is a silient period and must be the end of a data - if (startDataP != 0){ - parse = true; - break; - } - } - - //stream data to stream parsers - parseOregonStream(LOW, sampleCount); - - } - - //step the read pointer one step - uint8_t* nextBufferReadP = getNextBufferPointer(bufferReadP); - if (nextBufferReadP == startDataP) { //next pointer will point to startDataP. Data will overflow. Reset the data pointers. - startDataP = 0; - endDataP = 0; - prevValue = 0; - } - - //advance buffer pointer one step - bufferReadP = nextBufferReadP; - - prevValue = sampleCount; //update previous value - } - - if (!parse) { - return; - } - - if (startDataP == 0 || endDataP == 0) { - return; - } - - /* - * At this point the startDataP will point to the first high after a silent period - * and the endDataP will point at the first (low) silent period after the data data start. - */ - - //Serial.print((uintptr_t)startDataP); Serial.print(" - "); Serial.println((uintptr_t)endDataP); - - //Let all available parsers parse the data set now. - parseArctechSelfLearning(startDataP, endDataP); - //TODO: add more parsers here - - //reset the data pointers since the data have been parsed at this point - startDataP = 0; - endDataP = 0; - -}; //end radioTask - -void sendTCodedData(uint8_t* data, uint8_t T_long, uint8_t* timings, uint8_t repeat, uint8_t pause) { - ACTIVATE_RADIO_TRANSMITTER(); - for (uint8_t rep = 0; rep < repeat; ++rep) { - bool nextPinState = HIGH; - for (int i = 0; i < T_long; ++i) { - uint8_t timeIndex = (data[i / 4] >> (6 - (2 * (i % 4)))) & 0x03; - if (timings[timeIndex] > 0 || i == T_long - 1) { - if (nextPinState){ - TX_PIN_HIGH(); - }else{ - TX_PIN_LOW(); - } - delayMicroseconds(10 * timings[timeIndex]); - } - nextPinState = !nextPinState; - } - TX_PIN_LOW(); - if (rep < repeat - 1) { - delay(pause); - } - } - ACTIVATE_RADIO_RECEIVER(); -}; - -void sendSCodedData(uint8_t* data, uint8_t pulseCount, uint8_t repeat, uint8_t pause) { - ACTIVATE_RADIO_TRANSMITTER(); - for (uint8_t rep = 0; rep < repeat; ++rep) { - bool nextPinState = HIGH; - for (int i = 0; i < pulseCount; ++i) { - if (data[i] > 0 || i == pulseCount - 1) { - if (nextPinState){ - TX_PIN_HIGH(); - }else{ - TX_PIN_LOW(); - } - delayMicroseconds(data[i] * 10); - } - nextPinState = !nextPinState; - } - delay(pause); - } - TX_PIN_LOW(); - ACTIVATE_RADIO_RECEIVER(); -}; diff --git a/arduino/ArduinoTellstickDuo/rf.h b/arduino/ArduinoTellstickDuo/rf.h deleted file mode 100644 index c8507c5c..00000000 --- a/arduino/ArduinoTellstickDuo/rf.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef RF_H -#define RF_H - -#include "Arduino.h" - -#define ACTIVATE_RADIO_RECEIVER() (RFRX = true) -#define ACTIVATE_RADIO_TRANSMITTER() (RFRX = false) -#define IS_RADIO_RECIEVER_ON() (RFRX) -#define IS_RADIO_TRANSMITTER_ON() (!RFRX) - -extern volatile bool RFRX; - -void parseRadioRXBuffer(); -void sendTCodedData(uint8_t* data, uint8_t T_long, uint8_t* timings, uint8_t repeat, uint8_t pause); -void sendSCodedData(uint8_t* data, uint8_t pulseCount, uint8_t repeat, uint8_t pause); - -#endif //RF_H diff --git a/arduino/ArduinoTellstickDuo/usart.cpp b/arduino/ArduinoTellstickDuo/usart.cpp deleted file mode 100644 index f313a473..00000000 --- a/arduino/ArduinoTellstickDuo/usart.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "usart.h" -#include "rf.h" - -uint8_t Serial_rxBuffer[79]; - -void parseSerialForCommand() { - if (Serial.available() > 0) { - uint8_t rxDataSize = Serial.readBytesUntil('+', &Serial_rxBuffer[0], 79); - if (rxDataSize > 0) { - parseRxBuffer(&Serial_rxBuffer[0], 0, rxDataSize, false, 3, 0); - } - } -}; //end serialTask - -bool parseRxBuffer(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause) { - if (startIndex > endIndex) { - return false; - } - char c = buffer[startIndex]; - //Serial.print("DEBUG: char:"); Serial.println(c, DEC); - switch (c) { - case 'S': - return handleSCommand(buffer, startIndex + 1, endIndex, debug, repeat, pause); - case 'T': - return handleTCommand(buffer, startIndex + 1, endIndex, debug, repeat, pause); - case 'V': - Serial.println(F("+V2")); - return parseRxBuffer(buffer, startIndex + 1, endIndex, debug, repeat, pause); - case 'D': - return parseRxBuffer(buffer, startIndex + 1, endIndex, !debug, repeat, pause); - case 'P': - if (endIndex - startIndex + 1 < 3) { - return false; - } //at least {'P',[p-value],'+'} must be left in the buffer - return parseRxBuffer(buffer, startIndex + 2, endIndex, debug, repeat, buffer[startIndex + 1]); - case 'R': - if (endIndex - startIndex + 1 < 3) { - return false; - } //at least {'R',[r-value],'+'} must be left in the buffer - return parseRxBuffer(buffer, startIndex + 2, endIndex, debug, buffer[startIndex + 1], pause); - case '+': - return true; - default: - //Serial.print("DEBUG: unknown char: '"); Serial.print(c, BIN); Serial.println("'"); - return false; - } -}; //end parseRxBuffer - -bool handleSCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause) { - //Parse message received from serial - uint8_t S_data[78]; //78 pulses - uint8_t pulseCount = 0; - for (uint8_t i = startIndex; i <= endIndex; ++i) { - if (buffer[i] == '+') { - break; - } else if (i == endIndex) { - return false; - } else { - S_data[pulseCount++] = buffer[i]; - } - } - //Send message - sendSCodedData(&S_data[0], pulseCount, repeat, pause); - - //send confirmation over serial - Serial.println(F("+S")); - return true; -}; //end handleS - -bool handleTCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause) { - //Parse message received from serial - uint8_t T_data[72]; //0-188 pulses - if (endIndex - startIndex < 5) { - //Serial.println("DEBUG: wrong size!"); - return false; - } - uint8_t buff_p = startIndex; - uint8_t T_times[4] = {buffer[buff_p++], buffer[buff_p++], buffer[buff_p++], buffer[buff_p++]}; - uint8_t T_long = buffer[buff_p++]; - uint8_t T_bytes = 0; - if ( (T_long / 4.0) > (float)(T_long / 4) ) { - T_bytes = T_long / 4 + 1; - } else { - T_bytes = T_long / 4; - } - uint8_t j = 0; - while (j < T_bytes) { - if (buffer[buff_p] == '+') { - break; - } else if (buff_p >= endIndex) { - return false; - } else { - T_data[j++] = buffer[buff_p++]; - } - } - if ( j != T_bytes ) { - return false; - } - - //Send message - sendTCodedData(&T_data[0], T_long, &T_times[0], repeat, pause); - - //send confirmation over serial - Serial.println(F("+T")); - return parseRxBuffer(buffer, buff_p, endIndex, debug, repeat, pause); -}; //end handleT diff --git a/arduino/ArduinoTellstickDuo/usart.h b/arduino/ArduinoTellstickDuo/usart.h deleted file mode 100644 index b397ff19..00000000 --- a/arduino/ArduinoTellstickDuo/usart.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef USART_H -#define USART_H - -#include "Arduino.h" - -void parseSerialForCommand(); -bool parseRxBuffer(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause); -bool handleSCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause); -bool handleTCommand(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause); - -extern uint8_t Serial_rxBuffer[79]; - -#endif //USART_H diff --git a/arduino/HalMultiSensor/HalConfiguration.h b/arduino/HalMultiSensor/HalConfiguration.h deleted file mode 100644 index afab67fa..00000000 --- a/arduino/HalMultiSensor/HalConfiguration.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef HALCONFIGURATION_H -#define HALCONFIGURATION_H - -//#define ENABLE_DEBUG // comment out to disable debug - - -#define TIMER_MILLISECOND 60000 // poling in minutes -#define INDICATOR_PIN 13 // diode -#define TX_PIN 11 -#define DEVICE_BASE_ID 99 - -// POWER CONSUMPTION SENSOR -//#define POWERCON_ENABLED // comment out to disable sensor -#define POWERCON_SENSOR SensorPhotocell() -#define POWERCON_PROTOCOL ProtocolOregon(TX_PIN, DEVICE_BASE_ID + 0) -#define POWER_TIMER_MULTIPLIER 1 - -// TEMPERATURE SENSOR -#define TEMPERATURE_ENABLED // comment out to disable sensor -#define TEMPERATURE_SENSOR SensorDHT(DHT11, 10) -#define TEMPERATURE_PROTOCOL ProtocolOregon(TX_PIN, DEVICE_BASE_ID + 1) -#define TEMPERATURE_TIMER_MULTIPLIER 10 - -// LIGHT SENSOR -//#define LIGHT_ENABLED // comment out to disable sensor -#define LIGHT_SENSOR SensorBH1750() -#define LIGHT_PROTOCOL ProtocolOregon(TX_PIN, DEVICE_BASE_ID + 2) -#define LIGHT_TIMER_MULTIPLIER 10 - - -#endif // HALCONFIGURATION_H diff --git a/arduino/HalMultiSensor/HalInclude.h b/arduino/HalMultiSensor/HalInclude.h deleted file mode 100644 index bef0a17d..00000000 --- a/arduino/HalMultiSensor/HalInclude.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef HALDEFINITIONS_H -#define HALDEFINITIONS_H - -/////// SENSORS -#include "SensorBH1750.h" -#include "SensorDHT.h" -#include "SensorPhotocell.h" - -//////// PROTOCOLS -#include "ProtocolNexa.h" -#include "ProtocolOregon.h" - - -#endif // HALDEFINITIONS_H \ No newline at end of file diff --git a/arduino/HalMultiSensor/HalInterfaces.h b/arduino/HalMultiSensor/HalInterfaces.h deleted file mode 100644 index 2b858a98..00000000 --- a/arduino/HalMultiSensor/HalInterfaces.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef HALINTERFACES_H -#define HALINTERFACES_H - -#include -#include "HalConfiguration.h" - -// Utility functions - -#ifdef ENABLE_DEBUG - #define DEBUG(msg) \ - Serial.println(msg); \ - Serial.flush(); - #define DEBUGF(msg, ...) \ - static char buffer[80];\ - snprintf(buffer, sizeof(buffer), msg, __VA_ARGS__);\ - Serial.println(buffer);\ - Serial.flush(); -#else - #define DEBUG(msg) - #define DEBUGF(msg, ...) -#endif - - -inline void pulse(short pin, short count) -{ - while (--count >= 0) - { - digitalWrite(INDICATOR_PIN, HIGH); - delay(150); - digitalWrite(INDICATOR_PIN, LOW); - if (count != 0) delay(200); - } -} - -/////////////////////////////////////////////////////////////////////////// -// INTERFACES - -class Sensor -{ -public: - virtual void setup() = 0; -}; -class Protocol -{ -public: - virtual void setup() = 0; -}; - - - -struct PowerData -{ - unsigned int consumption; -}; -class SensorPowerConsumption : public Sensor -{ -public: - // returns number of pulses from power meter - virtual void read(PowerData& data) = 0; -}; -class ProtocolPowerConsumption : public Protocol -{ -public: - virtual void send(const PowerData& data) = 0; -}; - - -struct TemperatureData -{ - float temperature; - float humidity; -}; -class SensorTemperature : public Sensor -{ -public: - virtual void read(TemperatureData& data) = 0; -}; -class ProtocolTemperature : public Protocol -{ -public: - virtual void send(const TemperatureData& data) = 0; -}; - - -struct LightData -{ - unsigned int lumen; -}; -class SensorLight : public Sensor -{ -public: - virtual void read(LightData& data) = 0; -}; -class ProtocolLight : public Protocol -{ -public: - virtual void send(const LightData& data) = 0; -}; - - -#endif // HALINTERFACES_H diff --git a/arduino/HalMultiSensor/HalMultiSensor.ino b/arduino/HalMultiSensor/HalMultiSensor.ino deleted file mode 100644 index 0b9f3b4b..00000000 --- a/arduino/HalMultiSensor/HalMultiSensor.ino +++ /dev/null @@ -1,132 +0,0 @@ -/* -A interrupt based sensor device that reads multiple sensors and transmits -the data to a central location. -*/ -#include - -#include "HalConfiguration.h" -#include "HalInterfaces.h" -#include "HalInclude.h" -#include "Interrupt.h" - - -#ifndef POWERCON_ENABLED - #define POWER_TIMER_MULTIPLIER 1 -#endif -#ifndef TEMPERATURE_ENABLED - #define TEMPERATURE_TIMER_MULTIPLIER 1 -#endif -#ifndef LIGHT_ENABLED - #define LIGHT_TIMER_MULTIPLIER 1 -#endif -#define TIMER_MULTIPLIER_MAX \ - POWER_TIMER_MULTIPLIER * TEMPERATURE_TIMER_MULTIPLIER * LIGHT_TIMER_MULTIPLIER -unsigned int timerMultiplier = 0; - -// Sensors -SensorPowerConsumption* powerSensor; -SensorTemperature* tempSensor; -SensorLight* lightSensor; - -// Protocols -ProtocolPowerConsumption* powerProtocol; -ProtocolTemperature* tempProtocol; -ProtocolLight* lightProtocol; - - - -void timerInterruptFunc(); - -void setup() -{ - #ifdef ENABLE_DEBUG - Serial.begin(9600); - #endif - pinMode(INDICATOR_PIN, OUTPUT); - - // Setup Sensors and protocols - #ifdef POWERCON_ENABLED - DEBUG("Setup POWERCON_SENSOR"); - powerSensor = new POWERCON_SENSOR; - powerSensor->setup(); - powerProtocol = new POWERCON_PROTOCOL; - powerProtocol->setup(); - #endif - - #ifdef TEMPERATURE_ENABLED - DEBUG("Setup TEMPERATURE_SENSOR"); - tempSensor = new TEMPERATURE_SENSOR; - tempSensor->setup(); - tempProtocol = new TEMPERATURE_PROTOCOL; - tempProtocol->setup(); - #endif - - #ifdef LIGHT_ENABLED - DEBUG("Setup LIGHT_SENSOR"); - lightSensor = new LIGHT_SENSOR; - lightSensor->setup(); - lightProtocol = new LIGHT_PROTOCOL; - lightProtocol->setup(); - #endif - - DEBUG("Setup SLEEP_INTERRUPT"); - Interrupt::setWatchDogCallback(timerInterruptFunc); - Interrupt::setupWatchDogInterrupt(TIMER_MILLISECOND); // one minute scheduled interrupt - - - pulse(INDICATOR_PIN, 3); - DEBUG("Ready"); -} - - -void timerInterruptFunc() -{ - ++timerMultiplier; - if (timerMultiplier > TIMER_MULTIPLIER_MAX) - timerMultiplier = 1; -} - -void loop() -{ - digitalWrite(INDICATOR_PIN, HIGH); - - // Send power consumption - #ifdef POWERCON_ENABLED - if (timerMultiplier % POWER_TIMER_MULTIPLIER == 0) - { - static PowerData powerData; - powerSensor->read(powerData); // not needed, only here for future use - DEBUGF("Read POWERCON_SENSOR= consumption:%d", powerData.consumption); - powerProtocol->send(powerData); - } - #endif - - // Handle temperature sensor - #ifdef TEMPERATURE_ENABLED - if (timerMultiplier % TEMPERATURE_TIMER_MULTIPLIER == 0) - { - static TemperatureData tempData; - tempSensor->read(tempData); - DEBUGF("Read TEMPERATURE_SENSOR= temperature:%d, humidity:%d", (int)tempData.temperature, (int)tempData.humidity); - tempProtocol->send(tempData); - } - #endif - - // Handle light sensor - #ifdef LIGHT_ENABLED - if (timerMultiplier % LIGHT_TIMER_MULTIPLIER == 0) - { - static LightData lightData; - lightSensor->read(lightData); - DEBUGF("Read LIGHT_SENSOR= lumen:%d", lightData.lumen); - lightProtocol->send(lightData); - } - #endif - - digitalWrite(INDICATOR_PIN, LOW); - - DEBUG("Sleeping"); - Interrupt::sleep(); - DEBUG("Wakeup"); -} - diff --git a/arduino/HalMultiSensor/HalMultiSensorEnclosure.FCStd b/arduino/HalMultiSensor/HalMultiSensorEnclosure.FCStd deleted file mode 100644 index 89019798..00000000 Binary files a/arduino/HalMultiSensor/HalMultiSensorEnclosure.FCStd and /dev/null differ diff --git a/arduino/HalMultiSensor/HalMultiSensorEnclosure_bottom.stl b/arduino/HalMultiSensor/HalMultiSensorEnclosure_bottom.stl deleted file mode 100644 index 43e2e492..00000000 Binary files a/arduino/HalMultiSensor/HalMultiSensorEnclosure_bottom.stl and /dev/null differ diff --git a/arduino/HalMultiSensor/HalMultiSensorEnclosure_top.stl b/arduino/HalMultiSensor/HalMultiSensorEnclosure_top.stl deleted file mode 100644 index 6fe06d5e..00000000 Binary files a/arduino/HalMultiSensor/HalMultiSensorEnclosure_top.stl and /dev/null differ diff --git a/arduino/HalMultiSensor/Interrupt.cpp b/arduino/HalMultiSensor/Interrupt.cpp deleted file mode 100644 index 009af7e7..00000000 --- a/arduino/HalMultiSensor/Interrupt.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "Interrupt.h" -#include -#include -#include -#include "HalInterfaces.h" - -void emptyFunc(){} -bool Interrupt::wakeUpNow = false; -InterruptFunction Interrupt::pinCallback = emptyFunc; -InterruptFunction Interrupt::wdtCallback = emptyFunc; - - -void Interrupt::handlePinInterrupt() // the interrupt is handled here after wakeup -{ - (*Interrupt::pinCallback) (); - //Interrupt::wakeUp(); -} - -void Interrupt::sleep() -{ - /* - * The 5 different modes are: - * SLEEP_MODE_IDLE -the least power savings - * SLEEP_MODE_ADC - * SLEEP_MODE_PWR_SAVE - * SLEEP_MODE_STANDBY - * SLEEP_MODE_PWR_DOWN -the most power savings - * - * For now, we want as much power savings as possible, so we - * choose the according - * sleep mode: SLEEP_MODE_PWR_DOWN - */ - set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here - wakeUpNow = false; - - sleep_enable(); // enables the sleep bit in the mcucr register - // so sleep is possible. just a safety pin - - //power_adc_disable(); - //power_spi_disable(); - //power_usart0_disable(); - //power_timer0_disable(); - //power_timer1_disable(); - //power_timer2_disable(); - //power_twi_disable(); - //power_all_disable(); - - while( ! Interrupt::wakeUpNow) - { - sleep_mode(); // here the device is actually put to sleep!! - // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP - } - sleep_disable(); // first thing after waking from sleep: - // disable sleep... - - //power_adc_enable(); - //power_spi_enable(); - //power_usart0_enable(); - //power_timer0_enable(); - //power_timer1_enable(); - //power_timer2_enable(); - //power_twi_enable(); - //power_all_enable(); // during normal running time. -} - -void Interrupt::setupPinInterrupt(int pin) -{ - noInterrupts(); // disable all interrupts - - /* Now it is time to enable an interrupt. - * In the function call attachInterrupt(A, B, C) - * A can be either 0 or 1 for interrupts on pin 2 or 3. - * B Name of a function you want to execute at interrupt for A. - * C Trigger mode of the interrupt pin. can be: - * LOW a low level triggers - * CHANGE a change in level triggers - * RISING a rising edge of a level triggers - * FALLING a falling edge of a level triggers - * - * In all but the IDLE sleep modes only LOW can be used. - */ - attachInterrupt((pin == PIND2 ? 0 : 1), Interrupt::handlePinInterrupt, RISING); - - //detachInterrupt(0); // disables interrupt 0 on pin 2 so the - // wakeUpNow code will not be executed - - interrupts(); // enable all interrupts -} - -////////////////////////////////////////////////////////////////////////// -// Watchdog timer -uint16_t wdtTime; -int32_t wdtTimeLeft; - - -void Interrupt::handleWatchDogInterrupt() -{ - wdt_disable(); - if (wdtTime <= 0) - return; - DEBUGF("WDT interrupt, time=%u, timeLeft=%ld", wdtTime, wdtTimeLeft); - - if (wdtTimeLeft <= 0) - { - Interrupt::wakeUp(); - (*Interrupt::wdtCallback) (); - wdtTimeLeft = wdtTime; - } - - setupWatchDogInterrupt(); -} - -ISR(WDT_vect) -{ - Interrupt::handleWatchDogInterrupt(); -} - -void Interrupt::setupWatchDogInterrupt(int32_t milliseconds) -{ - wdtTimeLeft = wdtTime = milliseconds; - setupWatchDogInterrupt(); -} - -void Interrupt::setupWatchDogInterrupt() -{ - if (wdtTime <= 0){ - wdt_disable(); - return; - } - - noInterrupts(); - - unsigned short duration; - - if (8000 <= wdtTimeLeft){ - wdtTimeLeft -= 8000; - duration = (1 << WDP3) | (1 << WDP0); - } else if (4000 <= wdtTimeLeft){ - wdtTimeLeft -= 4000; - duration = (1 << WDP3); - } else if (2000 <= wdtTimeLeft){ - wdtTimeLeft -= 2000; - duration = (1 << WDP2) | (1 << WDP1) | (1 << WDP0); - } else if (1000 <= wdtTimeLeft){ - wdtTimeLeft -= 1000; - duration = (1 << WDP2) | (1 << WDP1); - } else if (500 <= wdtTimeLeft){ - wdtTimeLeft -= 500; - duration = (1 << WDP2) | (1 << WDP0); - } else if (256 <= wdtTimeLeft){ - wdtTimeLeft -= 256; - duration = (1 << WDP2); - } else if (128 <= wdtTimeLeft){ - wdtTimeLeft -= 128; - duration = (1 << WDP1) | (1 << WDP0); - } else if (64 <= wdtTimeLeft){ - wdtTimeLeft -= 64; - duration = (1 << WDP1); - } else if (32 <= wdtTimeLeft){ - wdtTimeLeft -= 32; - duration = (1 << WDP0); - } else { //(16 <= wdtTimeLeft){ - wdtTimeLeft -= 16; - duration = 0; - } - - wdt_reset(); - MCUSR &= ~(1 << WDRF); // reset status flag - - /* WDCE = Watchdog Change Enable - * - * WDTON(1) WDE WDIE Mode - * 1 0 0 Stopped - * 1 0 1 Interrupt - * 1 1 0 Reset - * 1 1 1 Interrupt first, reset on second trigger - * 0 x x Reset - */ - WDTCSR = (1 << WDCE) | (1< - -typedef void (*InterruptFunction) (); - -class Interrupt -{ -public: - static void wakeUp() { wakeUpNow = true; }; - static void sleep(); - static void setupPinInterrupt(int pin); - static void setupWatchDogInterrupt(int32_t milliseconds); - //static void setupTimerInterrupt(unsigned int milliseconds); - - static void setPinCallback(InterruptFunction callback){ Interrupt::pinCallback = callback;} - static void setWatchDogCallback(InterruptFunction callback){ Interrupt::wdtCallback = callback;} - - /* Should not be called externally, used as triggering functions */ - static void handlePinInterrupt(); - static void handleWatchDogInterrupt(); -private: - static bool wakeUpNow; - - static InterruptFunction pinCallback; - static InterruptFunction wdtCallback; - - static void setupWatchDogInterrupt(); - - // Disable constructors and copy operators - Interrupt() {}; - Interrupt(Interrupt const&); - void operator=(Interrupt const&); - -}; - - -#endif // INTERRUPT_H \ No newline at end of file diff --git a/arduino/HalMultiSensor/ProtocolNexa.cpp b/arduino/HalMultiSensor/ProtocolNexa.cpp deleted file mode 100644 index 8b137891..00000000 --- a/arduino/HalMultiSensor/ProtocolNexa.cpp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/arduino/HalMultiSensor/ProtocolNexa.h b/arduino/HalMultiSensor/ProtocolNexa.h deleted file mode 100644 index e70ac60a..00000000 --- a/arduino/HalMultiSensor/ProtocolNexa.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PROTOCOLNEXA_H -#define PROTOCOLNEXA_H - -#include "HalInterfaces.h" - - - -#endif // PROTOCOLNEXA_H diff --git a/arduino/HalMultiSensor/ProtocolOregon.cpp b/arduino/HalMultiSensor/ProtocolOregon.cpp deleted file mode 100644 index 96f04174..00000000 --- a/arduino/HalMultiSensor/ProtocolOregon.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include "ProtocolOregon.h" - -#define RF_DELAY 512 -#define RF_DELAY_LONG RF_DELAY*2 -#define RF_SEND_HIGH() digitalWrite(txPin, HIGH) -#define RF_SEND_LOW() digitalWrite(txPin, LOW) - - -void ProtocolOregon::setup() -{ - pinMode(txPin, OUTPUT); - RF_SEND_LOW(); -} - - -void ProtocolOregon::send(const PowerData& data) -{ - send(data.consumption, 0); -} - -void ProtocolOregon::send(const TemperatureData& data) -{ - send(data.temperature, data.humidity); -} - -void ProtocolOregon::send(const LightData& data) -{ - send(data.lumen, 0); -} - - - -void ProtocolOregon::send(float temperature, short humidity) -{ - byte buffer[9]; - setType(buffer, 0x1A,0x2D); //temperature/humidity sensor (THGR2228N) - setChannel(buffer, 0x20); - setId(buffer, address); //set id of the sensor, BB=187 - setBatteryLevel(buffer, true); // false : low, true : high - setTemperature(buffer, temperature); //org setTemperature(OregonMessageBuffer, 55.5); - setHumidity(buffer, humidity); - calculateAndSetChecksum(buffer); - - // Send the Message over RF - rfSend(buffer, sizeof(buffer)); - // Send a "pause" - RF_SEND_LOW(); - delayMicroseconds(RF_DELAY_LONG * 8); - // Send a copy of the first message. The v2.1 protocol send the message two RF_DELAYs - rfSend(buffer, sizeof(buffer)); - RF_SEND_LOW(); -} - -/** - * \brief Set the sensor type - * \param data Oregon message - * \param type Sensor type - */ -inline void ProtocolOregon::setType(byte data[], byte b1, byte b2) -{ - data[0] = b1; - data[1] = b2; -} - -/** - * \brief Set the sensor channel - * \param data Oregon message - * \param channel Sensor channel (0x10, 0x20, 0x30) - */ -inline void ProtocolOregon::setChannel(byte data[], byte channel) -{ - data[2] = channel; -} - - -inline void ProtocolOregon::setId(byte data[], byte id) -{ - data[3] = id; -} - -/** - * \param level false: low, true: high - */ -inline void ProtocolOregon::setBatteryLevel(byte data[], bool level) -{ - if (!level) data[4] = 0x0C; - else data[4] = 0x00; -} - -inline void ProtocolOregon::setTemperature(byte data[], float temp) -{ - // Set temperature sign - if (temp < 0) - { - data[6] = 0x08; - temp *= -1; - } - else - { - data[6] = 0x00; - } - - // Determine decimal and float part - int tempInt = (int)temp; - int td = (int)(tempInt / 10); - int tf = (int)round((float)((float)tempInt/10 - (float)td) * 10); - - int tempFloat = (int)round((float)(temp - (float)tempInt) * 10); - - // Set temperature decimal part - data[5] = (td << 4); - data[5] |= tf; - - // Set temperature float part - data[4] |= (tempFloat << 4); -} - -inline void ProtocolOregon::setHumidity(byte data[], byte hum) -{ - data[7] = (hum/10); - data[6] |= (hum - data[7]*10) << 4; -} - -inline void ProtocolOregon::calculateAndSetChecksum(byte data[]) -{ - int sum = 0; - for(byte i = 0; i<8;i++) - { - sum += (data[i]&0xF0) >> 4; - sum += (data[i]&0x0F); - } - data[8] = ((sum - 0x0A) & 0xFF); -} - - - - -//********************************************************************************************************* - - -/** - * \brief Send logical "0" over RF - * \details a zero bit be represented by an off-to-on transition - * \ of the RF signal at the middle of a clock period. - * \ Remember, the Oregon v2.1 protocol adds an inverted bit first - */ -inline void ProtocolOregon::sendZero(void) -{ - RF_SEND_HIGH(); - delayMicroseconds(RF_DELAY); - RF_SEND_LOW(); - delayMicroseconds(RF_DELAY_LONG); - RF_SEND_HIGH(); - delayMicroseconds(RF_DELAY); -} - -/** - * \brief Send logical "1" over RF - * \details a one bit be represented by an on-to-off transition - * \ of the RF signal at the middle of a clock period. - * \ Remember, the Oregon v2.1 protocol add an inverted bit first - */ -inline void ProtocolOregon::sendOne(void) -{ - RF_SEND_LOW(); - delayMicroseconds(RF_DELAY); - RF_SEND_HIGH(); - delayMicroseconds(RF_DELAY_LONG); - RF_SEND_LOW(); - delayMicroseconds(RF_DELAY); -} - - -/******************************************************************/ -/******************************************************************/ -/******************************************************************/ - -/** - * \brief Send a buffer over RF - * \param data Data to send - * \param length size of data array - */ -void ProtocolOregon::sendData(byte data[], byte length) -{ - for (byte i=0; i -#include "HalInterfaces.h" - - -class ProtocolOregon : public ProtocolTemperature, public ProtocolPowerConsumption, public ProtocolLight -{ -public: - ProtocolOregon(short pin, unsigned char address) : txPin(pin), address(address){}; - - virtual void setup(); - virtual void send(const TemperatureData& data); - virtual void send(const PowerData& data); - virtual void send(const LightData& data); - -private: - short txPin; - unsigned char address; - - void send(float temperature, short humidity); - void setType(byte *data, byte b1, byte b2); - void setChannel(byte *data, byte channel); - void setId(byte *data, byte id); - void setBatteryLevel(byte *data, bool level); - void setTemperature(byte *data, float temp); - void setHumidity(byte* data, byte hum); - void calculateAndSetChecksum(byte* data); - - void sendZero(void); - void sendOne(void); - void sendData(byte *data, byte length); - void rfSend(byte *data, byte size); -}; - -#endif // PROTOCOLOREGON_H diff --git a/arduino/HalMultiSensor/SensorBH1750.cpp b/arduino/HalMultiSensor/SensorBH1750.cpp deleted file mode 100644 index 87a79842..00000000 --- a/arduino/HalMultiSensor/SensorBH1750.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - -This is a library for the BH1750FVI Digital Light Sensor -breakout board. - -The board uses I2C for communication. 2 pins are required to -interface to the device. - - -based on Christopher Laws, March, 2013 code. - -*/ - -#include "SensorBH1750.h" -#include - - -#define BH1750_I2CADDR 0x23 - -// No active state -#define BH1750_POWER_DOWN 0x00 - -// Waiting for measurement command -#define BH1750_POWER_ON 0x01 - -// Reset data register value - not accepted in POWER_DOWN mode -#define BH1750_RESET 0x07 - -// Start measurement at 1lx resolution. Measurement time is approx 120ms. -#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 - -// Start measurement at 0.5lx resolution. Measurement time is approx 120ms. -#define BH1750_CONTINUOUS_HIGH_RES_MODE_2 0x11 - -// Start measurement at 4lx resolution. Measurement time is approx 16ms. -#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13 - -// Start measurement at 1lx resolution. Measurement time is approx 120ms. -// Device is automatically set to Power Down after measurement. -#define BH1750_ONE_TIME_HIGH_RES_MODE 0x20 - -// Start measurement at 0.5lx resolution. Measurement time is approx 120ms. -// Device is automatically set to Power Down after measurement. -#define BH1750_ONE_TIME_HIGH_RES_MODE_2 0x21 - -// Start measurement at 1lx resolution. Measurement time is approx 120ms. -// Device is automatically set to Power Down after measurement. -#define BH1750_ONE_TIME_LOW_RES_MODE 0x23 - - - -void SensorBH1750::setup() { - Wire.begin(); - //configure(BH1750_ONE_TIME_HIGH_RES_MODE); -} - - -void SensorBH1750::configure(uint8_t mode) { - switch (mode) { - case BH1750_CONTINUOUS_HIGH_RES_MODE: - case BH1750_CONTINUOUS_HIGH_RES_MODE_2: - case BH1750_CONTINUOUS_LOW_RES_MODE: - case BH1750_ONE_TIME_HIGH_RES_MODE: - case BH1750_ONE_TIME_HIGH_RES_MODE_2: - case BH1750_ONE_TIME_LOW_RES_MODE: - // apply a valid mode change - Wire.beginTransmission(BH1750_I2CADDR); - Wire.write(mode); - Wire.endTransmission(); - _delay_ms(10); - break; - default: - // Invalid measurement mode - DEBUG("Invalid measurement mode"); - break; - } -} - - -void SensorBH1750::read(LightData& data) { - configure(BH1750_ONE_TIME_HIGH_RES_MODE); - _delay_ms(200); // Wait for measurement - - Wire.beginTransmission(BH1750_I2CADDR); - Wire.requestFrom(BH1750_I2CADDR, 2); - uint16_t level = Wire.read(); - level <<= 8; - level |= Wire.read(); - Wire.endTransmission(); - - data.lumen = level/1.2; // convert to lux -} - diff --git a/arduino/HalMultiSensor/SensorBH1750.h b/arduino/HalMultiSensor/SensorBH1750.h deleted file mode 100644 index 7e9dc9df..00000000 --- a/arduino/HalMultiSensor/SensorBH1750.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SensorBH1750_H -#define SensorBH1750_H - -#include -#include "HalInterfaces.h" - - -class SensorBH1750 : public SensorLight{ -public: - virtual void setup(); - virtual void read(LightData& data); - -private: - unsigned int pulses; - - void configure(uint8_t mode); - -}; - -#endif // SensorBH1750_H - diff --git a/arduino/HalMultiSensor/SensorDHT.cpp b/arduino/HalMultiSensor/SensorDHT.cpp deleted file mode 100644 index e867d7f2..00000000 --- a/arduino/HalMultiSensor/SensorDHT.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* DHT library -MIT license -written by Adafruit Industries -*/ -// Modified by Ziver Koc -// - -#include "SensorDHT.h" - - -void SensorDHT::setup() -{ - // set up the pins! - pinMode(_pin, INPUT_PULLUP); - #ifdef __AVR - _bit = digitalPinToBitMask(_pin); - _port = digitalPinToPort(_pin); - #endif - _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for - // reading pulses from DHT sensor. -} - - -// Expect the signal line to be at the specified level for a period of time and -// return a count of loop cycles spent at that level (this cycle count can be -// used to compare the relative time of two pulses). If more than a millisecond -// ellapses without the level changing then the call fails with a 0 response. -// This is adapted from Arduino's pulseInLong function (which is only available -// in the very latest IDE versions): -// https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c -uint32_t SensorDHT::expectPulse(bool level) { - uint32_t count = 0; - // On AVR platforms use direct GPIO port access as it's much faster and better - // for catching pulses that are 10's of microseconds in length: - #ifdef __AVR - uint8_t portState = level ? _bit : 0; - while ((*portInputRegister(_port) & _bit) == portState) { - if (count++ >= _maxcycles) { - return 0; // Exceeded timeout, fail. - } - } - // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266 - // right now, perhaps bugs in direct port access functions?). - #else - while (digitalRead(_pin) == level) { - if (count++ >= _maxcycles) { - return 0; // Exceeded timeout, fail. - } - } - #endif - - return count; -} - - -void SensorDHT::read(TemperatureData& retData) -{ - // Reset 40 bits of received data to zero. - static uint8_t data[5]; - data[0] = data[1] = data[2] = data[3] = data[4] = 0; - - // Send start signal. See DHT datasheet for full signal diagram: - // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf - - // Go into high impedence state to let pull-up raise data line level and - // start the reading process. - digitalWrite(_pin, HIGH); - delay(250); - - // First set data line low for 20 milliseconds. - pinMode(_pin, OUTPUT); - digitalWrite(_pin, LOW); - delay(20); - - uint32_t cycles[80]; - { - // Turn off interrupts temporarily because the next sections are timing critical - // and we don't want any interruptions. - noInterrupts(); - - // End the start signal by setting data line high for 40 microseconds. - digitalWrite(_pin, HIGH); - delayMicroseconds(40); - - // Now start reading the data line to get the value from the DHT sensor. - pinMode(_pin, INPUT_PULLUP); - delayMicroseconds(10); // Delay a bit to let sensor pull data line low. - - // First expect a low signal for ~80 microseconds followed by a high signal - // for ~80 microseconds again. - if (expectPulse(LOW) == 0) { - DEBUG("DHT:Timeout waiting for start signal low pulse."); - interrupts(); - return; - } - if (expectPulse(HIGH) == 0) { - DEBUG("DHT:Timeout waiting for start signal high pulse."); - interrupts(); - return; - } - - // Now read the 40 bits sent by the sensor. Each bit is sent as a 50 - // microsecond low pulse followed by a variable length high pulse. If the - // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds - // then it's a 1. We measure the cycle count of the initial 50us low pulse - // and use that to compare to the cycle count of the high pulse to determine - // if the bit is a 0 (high state cycle count < low state cycle count), or a - // 1 (high state cycle count > low state cycle count). Note that for speed all - // the pulses are read into a array and then examined in a later step. - for (int i=0; i<80; i+=2) { - cycles[i] = expectPulse(LOW); - cycles[i+1] = expectPulse(HIGH); - } - - interrupts(); - } // Timing critical code is now complete. - - // Inspect pulses and determine which ones are 0 (high state cycle count < low - // state cycle count), or 1 (high state cycle count > low state cycle count). - for (int i=0; i<40; ++i) { - uint32_t lowCycles = cycles[2*i]; - uint32_t highCycles = cycles[2*i+1]; - if ((lowCycles == 0) || (highCycles == 0)) { - DEBUG("DHT:Timeout waiting for pulse."); - return; - } - data[i/8] <<= 1; - // Now compare the low and high cycle times to see if the bit is a 0 or 1. - if (highCycles > lowCycles) { - // High cycles are greater than 50us low cycle count, must be a 1. - data[i/8] |= 1; - } - // Else high cycles are less than (or equal to, a weird case) the 50us low - // cycle count so this must be a zero. Nothing needs to be changed in the - // stored data. - } - - - // Check we read 40 bits and that the checksum matches. - if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { - switch (_type) { - case DHT11: - retData.temperature = data[2]; - retData.humidity = data[0]; - break; - case DHT22: - case DHT21: - retData.temperature = data[2] & 0x7F; - retData.temperature *= 256; - retData.temperature += data[3]; - retData.temperature *= 0.1; - if (data[2] & 0x80) { - retData.temperature *= -1; - } - retData.humidity = data[0]; - retData.humidity *= 256; - retData.humidity += data[1]; - retData.humidity *= 0.1; - break; - } - } - else { - DEBUG("DHT:Checksum failure!"); - } -} \ No newline at end of file diff --git a/arduino/HalMultiSensor/SensorDHT.h b/arduino/HalMultiSensor/SensorDHT.h deleted file mode 100644 index 04e2559a..00000000 --- a/arduino/HalMultiSensor/SensorDHT.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef SensorDHT_h -#define SensorDHT_h - -#include -#include "HalInterfaces.h" - - -// Define types of sensors. -#define DHT11 11 -#define DHT22 22 -#define DHT21 21 - - -class SensorDHT : public SensorTemperature -{ -public: - SensorDHT(uint8_t type, uint8_t pin) : _type(type), _pin(pin) {}; - - virtual void setup(); - virtual void read(TemperatureData& data); - -private: - uint8_t _type, _pin; - uint32_t _maxcycles; - #ifdef __AVR - // Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask - // for the digital pin connected to the DHT. Other platforms will use digitalRead. - uint8_t _bit, _port; - #endif - - uint32_t expectPulse(bool level); -}; -#endif diff --git a/arduino/HalMultiSensor/SensorPhotocell.cpp b/arduino/HalMultiSensor/SensorPhotocell.cpp deleted file mode 100644 index 476c529e..00000000 --- a/arduino/HalMultiSensor/SensorPhotocell.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "SensorPhotocell.h" -#include - -unsigned int SensorPhotocell::pulse = 0; - -void SensorPhotocell::interruptHandler() -{ - digitalWrite(INDICATOR_PIN, HIGH); - DEBUG("PHCELL: INTERRUPT"); - ++pulse; - digitalWrite(INDICATOR_PIN, LOW); -} - - -void SensorPhotocell::setup() -{ - Interrupt::setPinCallback(SensorPhotocell::interruptHandler); - Interrupt::setupPinInterrupt(PC2); //PC3 -} - -void SensorPhotocell::read(PowerData& data) -{ - data.consumption = pulse; - pulse = 0; -} diff --git a/arduino/HalMultiSensor/SensorPhotocell.h b/arduino/HalMultiSensor/SensorPhotocell.h deleted file mode 100644 index e84ecda1..00000000 --- a/arduino/HalMultiSensor/SensorPhotocell.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SensorPhotocell_H -#define SensorPhotocell_H - -#include "HalInterfaces.h" -#include "Interrupt.h" - - -class SensorPhotocell : public SensorPowerConsumption -{ -public: - virtual void setup(); - virtual void read(PowerData& data); - -private: - static unsigned int pulse; - - static void interruptHandler(); -}; - -#endif // SensorPhotocell_H diff --git a/arduino/NexaTellstick/NexaTellstick.ino b/arduino/NexaTellstick/NexaTellstick.ino deleted file mode 100644 index b8b2e274..00000000 --- a/arduino/NexaTellstick/NexaTellstick.ino +++ /dev/null @@ -1,155 +0,0 @@ -#include "NexaSelfLearningReceiver.h" - -#define TX_PIN 10 -#define RX_PIN 4 -#define RX_LED 13 - -//Radio RX -NexaSelfLearningReceiver receiver = NexaSelfLearningReceiver(RX_PIN, RX_LED); -short dim = 0; -uint64_t receivedSignal = 0; - -//Serial RX -byte rxBuffer[79]; - -void setup(){ - Serial.begin(9600); -}; - -void loop(){ - - //Receive and execute command over serial - if(Serial.available() > 0){ - uint8_t rxDataSize = Serial.readBytesUntil('+', &rxBuffer[0], 79); - if(rxDataSize > 0){ - if(parseRxBuffer(&rxBuffer[0], 0, rxDataSize, false, 3, 0)){ - //Serial.println(F("DEBUG:PARSE OK")); - }else{ - //Serial.println(F("DEBUG:PARSE ERROR")); - } - } - } - - //Receive signal over air and send it over serial - receivedSignal = receiver.receiveSignal(NULL, NULL, NULL, NULL, &dim, 100); - if(receivedSignal > 0){ - Serial.print(F("+Wclass:command;protocol:arctech;model:selflearning;data:0x")); - uint8_t hexToSend = (dim == NULL ? 8 : 9); - for(int8_t i = hexToSend-1; i >= 0; --i){ - Serial.print( (byte)((receivedSignal>>(4*i))&0x0F), HEX); - } - Serial.println(F(";")); - } - -}; - -bool parseRxBuffer(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause){ - if(startIndex > endIndex){ - return false; - } - char c = buffer[startIndex]; - //Serial.print("DEBUG: char:"); Serial.println(c, DEC); - switch(c){ - case 'S': - return handleS(buffer, startIndex+1, endIndex, debug, repeat, pause); - case 'T': - return handleT(buffer, startIndex+1, endIndex, debug, repeat, pause); - case 'V': - Serial.println(F("+V2")); - return parseRxBuffer(buffer, startIndex+1, endIndex, debug, repeat, pause); - case 'D': - return parseRxBuffer(buffer, startIndex+1, endIndex, !debug, repeat, pause); - case 'P': - if(endIndex-startIndex+1 < 3){return false;} //at least {'P',[p-value],'+'} must be left in the buffer - return parseRxBuffer(buffer, startIndex+2, endIndex, debug, repeat, buffer[startIndex+1]); - case 'R': - if(endIndex-startIndex+1 < 3){return false;} //at least {'R',[r-value],'+'} must be left in the buffer - return parseRxBuffer(buffer, startIndex+2, endIndex, debug, buffer[startIndex+1], pause); - case '+': - return true; - default: - //Serial.print("DEBUG: unknown char: '"); Serial.print(c, BIN); Serial.println("'"); - return false; - } -}; - -bool handleS(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause){ - //Parse message received from serial - uint8_t S_data[78]; //78 pulses - uint8_t pulseCount = 0; - for(uint8_t i = startIndex; i <= endIndex; ++i){ - if(buffer[i] == '+'){ - break; - }else if(i == endIndex){ - return false; - }else{ - S_data[pulseCount++] = buffer[i]; - } - } - //Send message - for(uint8_t rep = 0; rep < repeat; ++rep){ - bool nextPinState = HIGH; - for(int i = 0; i < pulseCount; ++i){ - if(S_data[i] > 0 || i == pulseCount-1){ - digitalWrite(TX_PIN, nextPinState); - delayMicroseconds(S_data[i]*10); - } - nextPinState = !nextPinState; - } - delay(pause); - } - //send confirmation over serial - Serial.println(F("+S")); - return true; -}; - -bool handleT(byte* buffer, uint8_t startIndex, uint8_t endIndex, bool debug, uint8_t repeat, uint8_t pause){ - //Parse message received from serial - uint8_t T_data[72]; //0-188 pulses - if(endIndex - startIndex < 5){ - //Serial.println("DEBUG: wrong size!"); - return false; - } - uint8_t buff_p = startIndex; - uint8_t T_times[4] = {buffer[buff_p++], buffer[buff_p++], buffer[buff_p++], buffer[buff_p++]}; - uint8_t T_long = buffer[buff_p++]; - uint8_t T_bytes = 0; - if( (T_long/4.0) > (float)(T_long/4) ){ - T_bytes = T_long/4 + 1; - }else{ - T_bytes = T_long/4; - } - uint8_t j = 0; - while(j < T_bytes){ - if(buffer[buff_p] == '+'){ - break; - }else if(buff_p >= endIndex){ - return false; - }else{ - T_data[j++] = buffer[buff_p++]; - } - } - if( j != T_bytes ){ - return false; - } - //Send message - for(uint8_t rep = 0; rep < repeat; ++rep){ - bool nextPinState = HIGH; - for(int i = 0; i < T_long; ++i){ - uint8_t timeIndex = (T_data[i/4]>>(6-(2*(i%4))))&0x03; - if(T_times[timeIndex] > 0 || i == T_long-1){ - digitalWrite(TX_PIN, nextPinState); - delayMicroseconds(10*T_times[timeIndex]); - } - nextPinState = !nextPinState; - } - digitalWrite(TX_PIN, LOW); - if(rep < repeat-1){ - delay(pause); - } - } - //send confirmation over serial - Serial.println(F("+T")); - return parseRxBuffer(buffer, buff_p, endIndex, debug, repeat, pause); -}; - diff --git a/arduino/lib/NexaControl b/arduino/lib/NexaControl deleted file mode 160000 index 5fd54293..00000000 --- a/arduino/lib/NexaControl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5fd5429375b3fffbf0bdd041d493d5c6ff0c156a diff --git a/build.gradle b/build.gradle deleted file mode 100644 index d3876ef0..00000000 --- a/build.gradle +++ /dev/null @@ -1,126 +0,0 @@ -plugins { - id 'java' - id 'application' -} - -/* - * The MIT License (MIT) - * - * Copyright (c) 2025 Ziver Koc - * - * 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. - */ - -// ------------------------------------ -// Hal common configuration -// ------------------------------------ - -allprojects { - repositories { - mavenLocal() - mavenCentral() - } -} - -subprojects { - apply plugin: 'java-library' - - dependencies { - //implementation 'se.koc:zutil:1.0.314' - implementation 'se.koc:zutil:1.0.0-SNAPSHOT' - - testImplementation 'junit:junit:4.12' - testImplementation 'org.hamcrest:hamcrest-core:2.2' - } - - sourceSets { - main { - java { - srcDirs 'src' - } - // We do not want the resource folder to be included in the jar file - //resources { - // srcDir 'resource' - //} - } - test { - java { - srcDirs 'test' - } - } - } - - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:deprecation" - //options.compilerArgs << "-Xlint:unchecked" - } -} - -// ------------------------------------ -// Hal general configuration -// ------------------------------------ - -dependencies { - project.subprojects.each { subProject -> - runtimeOnly subProject - } -} - -distributions { - main { - contents { - // from root project - from 'hal.conf.example' - from 'logging.properties' - from 'run.sh' - - // from subprojects - project.subprojects.each { subProject -> - into('bin') { - from "${subProject.projectDir}/resources/bin" - } - into('web') { - from "${subProject.projectDir}/resources/web" - } - into('resources') { - from ("${subProject.projectDir}/resources") { - exclude 'bin' - exclude 'web' - } - } - } - } - } -} - -distTar.enabled = false -distZip.enabled = false -assemble.dependsOn(installDist) - -project.gradle.startParameter.taskNames.each { taskName -> - if (taskName == 'distZip') { - distZip.enabled = true - } -} - -application { - mainClass = 'se.hal.HalServer' -} - -startScripts.enabled = false diff --git a/build.xml b/build.xml new file mode 100755 index 00000000..e27ffe9d --- /dev/null +++ b/build.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/Z-Stick_Gen5_Drivers.zip b/external/Z-Stick_Gen5_Drivers.zip deleted file mode 100644 index c5b3356e..00000000 Binary files a/external/Z-Stick_Gen5_Drivers.zip and /dev/null differ diff --git a/external/tellstick-core/AUTHORS.txt b/external/tellstick-core/AUTHORS.txt deleted file mode 100644 index 58bd0e4e..00000000 --- a/external/tellstick-core/AUTHORS.txt +++ /dev/null @@ -1,7 +0,0 @@ -telldus-core has been developed by : - - Micke Prag - Fredrik Jacobsson - Stefan Persson - -The package is maintained by Micke Prag diff --git a/external/tellstick-core/LICENSE.txt b/external/tellstick-core/LICENSE.txt deleted file mode 100644 index 4362b491..00000000 --- a/external/tellstick-core/LICENSE.txt +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/external/tellstick-core/Protocol.cpp b/external/tellstick-core/Protocol.cpp deleted file mode 100644 index 256df73d..00000000 --- a/external/tellstick-core/Protocol.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/Protocol.h" -#include -#include -#include - -#include "client/telldus-core.h" -#include "service/ControllerMessage.h" -#include "service/ProtocolBrateck.h" -#include "service/ProtocolComen.h" -#include "service/ProtocolEverflourish.h" -#include "service/ProtocolFineoffset.h" -#include "service/ProtocolFuhaote.h" -#include "service/ProtocolGroup.h" -#include "service/ProtocolHasta.h" -#include "service/ProtocolIkea.h" -#include "service/ProtocolMandolyn.h" -#include "service/ProtocolNexa.h" -#include "service/ProtocolOregon.h" -#include "service/ProtocolRisingSun.h" -#include "service/ProtocolSartano.h" -#include "service/ProtocolScene.h" -#include "service/ProtocolSilvanChip.h" -#include "service/ProtocolUpm.h" -#include "service/ProtocolWaveman.h" -#include "service/ProtocolX10.h" -#include "service/ProtocolYidong.h" -#include "common/Strings.h" - -class Protocol::PrivateData { -public: - ParameterMap parameterList; - std::wstring model; -}; - -Protocol::Protocol() { - d = new PrivateData; -} - -Protocol::~Protocol(void) { - delete d; -} - -std::wstring Protocol::model() const { - std::wstring strModel = d->model; - // Strip anything after : if it is found - size_t pos = strModel.find(L":"); - if (pos != std::wstring::npos) { - strModel = strModel.substr(0, pos); - } - - return strModel; -} - -void Protocol::setModel(const std::wstring &model) { - d->model = model; -} - -void Protocol::setParameters(const ParameterMap ¶meterList) { - d->parameterList = parameterList; -} - -std::wstring Protocol::getStringParameter(const std::wstring &name, const std::wstring &defaultValue) const { - ParameterMap::const_iterator it = d->parameterList.find(name); - if (it == d->parameterList.end()) { - return defaultValue; - } - return it->second; -} - -int Protocol::getIntParameter(const std::wstring &name, int min, int max) const { - std::wstring value = getStringParameter(name, L""); - if (value == L"") { - return min; - } - std::wstringstream st; - st << value; - int intValue = 0; - st >> intValue; - if (intValue < min) { - return min; - } - if (intValue > max) { - return max; - } - return intValue; -} - -bool Protocol::checkBit(int data, int bitno) { - return ((data >> bitno)&0x01); -} - - -Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname) { - if (TelldusCore::comparei(protocolname, L"arctech")) { - return new ProtocolNexa(); - - } else if (TelldusCore::comparei(protocolname, L"brateck")) { - return new ProtocolBrateck(); - - } else if (TelldusCore::comparei(protocolname, L"comen")) { - return new ProtocolComen(); - - } else if (TelldusCore::comparei(protocolname, L"everflourish")) { - return new ProtocolEverflourish(); - - } else if (TelldusCore::comparei(protocolname, L"fuhaote")) { - return new ProtocolFuhaote(); - - } else if (TelldusCore::comparei(protocolname, L"hasta")) { - return new ProtocolHasta(); - - } else if (TelldusCore::comparei(protocolname, L"ikea")) { - return new ProtocolIkea(); - - } else if (TelldusCore::comparei(protocolname, L"risingsun")) { - return new ProtocolRisingSun(); - - } else if (TelldusCore::comparei(protocolname, L"sartano")) { - return new ProtocolSartano(); - - } else if (TelldusCore::comparei(protocolname, L"silvanchip")) { - return new ProtocolSilvanChip(); - - } else if (TelldusCore::comparei(protocolname, L"upm")) { - return new ProtocolUpm(); - - } else if (TelldusCore::comparei(protocolname, L"waveman")) { - return new ProtocolWaveman(); - - } else if (TelldusCore::comparei(protocolname, L"x10")) { - return new ProtocolX10(); - - } else if (TelldusCore::comparei(protocolname, L"yidong")) { - return new ProtocolYidong(); - - } else if (TelldusCore::comparei(protocolname, L"group")) { - return new ProtocolGroup(); - - } else if (TelldusCore::comparei(protocolname, L"scene")) { - return new ProtocolScene(); - } - - return 0; -} - -std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { - std::list parameters; - if (TelldusCore::comparei(protocolName, L"arctech")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"brateck")) { - parameters.push_back("house"); - - } else if (TelldusCore::comparei(protocolName, L"comen")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"everflourish")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { - parameters.push_back("code"); - - } else if (TelldusCore::comparei(protocolName, L"hasta")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"ikea")) { - parameters.push_back("system"); - parameters.push_back("units"); - // parameters.push_back("fade"); - - } else if (TelldusCore::comparei(protocolName, L"risingsun")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"sartano")) { - parameters.push_back("code"); - - } else if (TelldusCore::comparei(protocolName, L"silvanchip")) { - parameters.push_back("house"); - - } else if (TelldusCore::comparei(protocolName, L"upm")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"waveman")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"x10")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"yidong")) { - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"group")) { - parameters.push_back("devices"); - - } else if (TelldusCore::comparei(protocolName, L"scene")) { - parameters.push_back("devices"); - } - - return parameters; -} - -std::list Protocol::decodeData(const std::string &fullData) { - std::list retval; - std::string decoded = ""; - - ControllerMessage dataMsg(fullData); - if ( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) { - decoded = ProtocolNexa::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - decoded = ProtocolWaveman::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - decoded = ProtocolSartano::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } else if (TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) { - decoded = ProtocolEverflourish::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } else if (TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) { - decoded = ProtocolFineoffset::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } else if (TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) { - decoded = ProtocolMandolyn::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } else if (TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) { - decoded = ProtocolOregon::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } else if (TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { - decoded = ProtocolX10::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } else if (TelldusCore::comparei(dataMsg.protocol(), L"hasta") ) { - decoded = ProtocolHasta::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } - - return retval; -} diff --git a/external/tellstick-core/Protocol.h b/external/tellstick-core/Protocol.h deleted file mode 100644 index a4e7e6cd..00000000 --- a/external/tellstick-core/Protocol.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOL_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOL_H_ - -#include -#include -#include -#include "client/telldus-core.h" - -typedef std::map ParameterMap; - -class Controller; - -class Protocol { -public: - Protocol(); - virtual ~Protocol(void); - - static Protocol *getProtocolInstance(const std::wstring &protocolname); - static std::list getParametersForProtocol(const std::wstring &protocolName); - static std::list decodeData(const std::string &fullData); - - virtual int methods() const = 0; - std::wstring model() const; - void setModel(const std::wstring &model); - void setParameters(const ParameterMap ¶meterList); - - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0; - -protected: - virtual std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; - virtual int getIntParameter(const std::wstring &name, int min, int max) const; - - static bool checkBit(int data, int bit); - -private: - class PrivateData; - PrivateData *d; -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOL_H_ diff --git a/external/tellstick-core/ProtocolBrateck.cpp b/external/tellstick-core/ProtocolBrateck.cpp deleted file mode 100644 index ab03387c..00000000 --- a/external/tellstick-core/ProtocolBrateck.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolBrateck.h" -#include - -int ProtocolBrateck::methods() const { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; -} - -std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) { - const char S = '!'; - const char L = 'V'; - const char B1[] = {L, S, L, S, 0}; - const char BX[] = {S, L, L, S, 0}; - const char B0[] = {S, L, S, L, 0}; - const char BUP[] = {L, S, L, S, S, L, S, L, S, L, S, L, S, L, S, L, S, 0}; - const char BSTOP[] = {S, L, S, L, L, S, L, S, S, L, S, L, S, L, S, L, S, 0}; - const char BDOWN[] = {S, L, S, L, S, L, S, L, S, L, S, L, L, S, L, S, S, 0}; - - std::string strReturn; - std::wstring strHouse = this->getStringParameter(L"house", L""); - if (strHouse == L"") { - return ""; - } - - for( size_t i = 0; i < strHouse.length(); ++i ) { - if (strHouse[i] == '1') { - strReturn.insert(0, B1); - } else if (strHouse[i] == '-') { - strReturn.insert(0, BX); - } else if (strHouse[i] == '0') { - strReturn.insert(0, B0); - } - } - - strReturn.insert(0, "S"); - if (method == TELLSTICK_UP) { - strReturn.append(BUP); - } else if (method == TELLSTICK_DOWN) { - strReturn.append(BDOWN); - } else if (method == TELLSTICK_STOP) { - strReturn.append(BSTOP); - } else { - return ""; - } - strReturn.append("+"); - - return strReturn; -} diff --git a/external/tellstick-core/ProtocolBrateck.h b/external/tellstick-core/ProtocolBrateck.h deleted file mode 100644 index c533308a..00000000 --- a/external/tellstick-core/ProtocolBrateck.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ - -#include -#include "service/Protocol.h" - -class ProtocolBrateck : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ diff --git a/external/tellstick-core/ProtocolComen.cpp b/external/tellstick-core/ProtocolComen.cpp deleted file mode 100644 index dfc7d38d..00000000 --- a/external/tellstick-core/ProtocolComen.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolComen.h" -#include - -int ProtocolComen::methods() const { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); -} - -int ProtocolComen::getIntParameter(const std::wstring &name, int min, int max) const { - if (name.compare(L"house") == 0) { - int intHouse = Protocol::getIntParameter(L"house", 1, 16777215); - // The last two bits must be hardcoded - intHouse <<= 2; - intHouse += 2; - return intHouse; - } - return Protocol::getIntParameter(name, min, max); -} diff --git a/external/tellstick-core/ProtocolComen.h b/external/tellstick-core/ProtocolComen.h deleted file mode 100644 index f43167a8..00000000 --- a/external/tellstick-core/ProtocolComen.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ - -#include -#include "service/ProtocolNexa.h" - -class ProtocolComen : public ProtocolNexa { -public: - virtual int methods() const; - -protected: - virtual int getIntParameter(const std::wstring &name, int min, int max) const; -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ diff --git a/external/tellstick-core/ProtocolEverflourish.cpp b/external/tellstick-core/ProtocolEverflourish.cpp deleted file mode 100644 index cc193931..00000000 --- a/external/tellstick-core/ProtocolEverflourish.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolEverflourish.h" -#include -#include -#include -#include "service/ControllerMessage.h" - -int ProtocolEverflourish::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; -} - -std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, Controller *) { - unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383); - unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1; - unsigned char action; - - if (method == TELLSTICK_TURNON) { - action = 15; - } else if (method == TELLSTICK_TURNOFF) { - action = 0; - } else if (method == TELLSTICK_LEARN) { - action = 10; - } else { - return ""; - } - - const char ssss = 85; - const char sssl = 84; // 0 - const char slss = 69; // 1 - - const char bits[2] = {sssl, slss}; - int i, check; - - std::string strCode; - - deviceCode = (deviceCode << 2) | intCode; - - check = calculateChecksum(deviceCode); - - char preamble[] = {'R', 5, 'T', 114, 60, 1, 1, 105, ssss, ssss, 0}; - strCode.append(preamble); - - for(i = 15; i >= 0; i--) { - strCode.append(1, bits[(deviceCode >> i)&0x01]); - } - for(i = 3; i >= 0; i--) { - strCode.append(1, bits[(check >> i)&0x01]); - } - for(i = 3; i >= 0; i--) { - strCode.append(1, bits[(action >> i)&0x01]); - } - - strCode.append(1, ssss); - strCode.append(1, '+'); - - return strCode; -} - -// The calculation used in this function is provided by Frank Stevenson -unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { - unsigned int bits[16] = { - 0xf, 0xa, 0x7, 0xe, - 0xf, 0xd, 0x9, 0x1, - 0x1, 0x2, 0x4, 0x8, - 0x3, 0x6, 0xc, 0xb - }; - unsigned int bit = 1; - unsigned int res = 0x5; - int i; - unsigned int lo, hi; - - if ((x & 0x3) == 3) { - lo = x & 0x00ff; - hi = x & 0xff00; - lo += 4; - if (lo>0x100) { - lo = 0x12; - } - x = lo | hi; - } - - for(i = 0; i < 16; i++) { - if (x & bit) { - res = res ^ bits[i]; - } - bit = bit << 1; - } - - return res; -} - -std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) { - uint64_t allData; - unsigned int house = 0; - unsigned int unit = 0; - unsigned int method = 0; - - allData = dataMsg.getInt64Parameter("data"); - - house = allData & 0xFFFC00; - house >>= 10; - - unit = allData & 0x300; - unit >>= 8; - unit++; // unit from 1 to 4 - - method = allData & 0xF; - - if(house > 16383 || unit < 1 || unit > 4) { - // not everflourish - return ""; - } - - std::stringstream retString; - retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:"; - if(method == 0) { - retString << "turnoff;"; - } else if(method == 15) { - retString << "turnon;"; - } else if(method == 10) { - retString << "learn;"; - } else { - // not everflourish - return ""; - } - - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolEverflourish.h b/external/tellstick-core/ProtocolEverflourish.h deleted file mode 100644 index ae4abf7c..00000000 --- a/external/tellstick-core/ProtocolEverflourish.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ - -#include -#include "service/Protocol.h" -#include "service/ControllerMessage.h" - -class ProtocolEverflourish : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(const ControllerMessage &dataMsg); - -private: - static unsigned int calculateChecksum(unsigned int x); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ diff --git a/external/tellstick-core/ProtocolFineoffset.cpp b/external/tellstick-core/ProtocolFineoffset.cpp deleted file mode 100644 index 2fd6f5ae..00000000 --- a/external/tellstick-core/ProtocolFineoffset.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolFineoffset.h" -#include -#include -#include -#include -#include "common/Strings.h" - -std::string ProtocolFineoffset::decodeData(const ControllerMessage &dataMsg) { - std::string data = dataMsg.getParameter("data"); - if (data.length() < 8) { - return ""; - } - - // Checksum currently not used - // uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); - data = data.substr(0, data.length()-2); - - uint8_t humidity = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); - data = data.substr(0, data.length()-2); - - uint16_t value = (uint16_t)TelldusCore::hexTo64l(data.substr(data.length()-3)); - double temperature = (value & 0x7FF)/10.0; - - value >>= 11; - if (value & 1) { - temperature = -temperature; - } - data = data.substr(0, data.length()-3); - - uint16_t id = (uint16_t)TelldusCore::hexTo64l(data) & 0xFF; - - std::stringstream retString; - retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:"; - - if (humidity <= 100) { - retString << "temperaturehumidity;humidity:" << static_cast(humidity) << ";"; - } else if (humidity == 0xFF) { - retString << "temperature;"; - } else { - return ""; - } - - retString << "temp:" << std::fixed << std::setprecision(1) << temperature << ";"; - - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolFineoffset.h b/external/tellstick-core/ProtocolFineoffset.h deleted file mode 100644 index b3bc3ce1..00000000 --- a/external/tellstick-core/ProtocolFineoffset.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ - -#include -#include "service/Protocol.h" -#include "service/ControllerMessage.h" - -class ProtocolFineoffset : public Protocol { -public: - static std::string decodeData(const ControllerMessage &dataMsg); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ diff --git a/external/tellstick-core/ProtocolFuhaote.cpp b/external/tellstick-core/ProtocolFuhaote.cpp deleted file mode 100644 index 7254520e..00000000 --- a/external/tellstick-core/ProtocolFuhaote.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolFuhaote.h" -#include - -int ProtocolFuhaote::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) { - const char S = 19; - const char L = 58; - const char B0[] = {S, L, L, S, 0}; - const char B1[] = {L, S, L, S, 0}; - const char OFF[] = {S, L, S, L, S, L, L, S, 0}; - const char ON[] = {S, L, L, S, S, L, S, L, 0}; - - std::string strReturn = "S"; - std::wstring strCode = this->getStringParameter(L"code", L""); - if (strCode == L"") { - return ""; - } - - // House code - for(size_t i = 0; i < 5; ++i) { - if (strCode[i] == '0') { - strReturn.append(B0); - } else if (strCode[i] == '1') { - strReturn.append(B1); - } - } - // Unit code - for(size_t i = 5; i < 10; ++i) { - if (strCode[i] == '0') { - strReturn.append(B0); - } else if (strCode[i] == '1') { - strReturn.append(1, S); - strReturn.append(1, L); - strReturn.append(1, S); - strReturn.append(1, L); - } - } - - if (method == TELLSTICK_TURNON) { - strReturn.append(ON); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(OFF); - } else { - return ""; - } - - strReturn.append(1, S); - strReturn.append("+"); - return strReturn; -} - diff --git a/external/tellstick-core/ProtocolFuhaote.h b/external/tellstick-core/ProtocolFuhaote.h deleted file mode 100644 index 2618ef86..00000000 --- a/external/tellstick-core/ProtocolFuhaote.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ - -#include -#include "service/Protocol.h" - -class ProtocolFuhaote : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ diff --git a/external/tellstick-core/ProtocolGroup.cpp b/external/tellstick-core/ProtocolGroup.cpp deleted file mode 100644 index 4c4d0d15..00000000 --- a/external/tellstick-core/ProtocolGroup.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolGroup.h" -#include - -int ProtocolGroup::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; -} - -std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { - return ""; -} diff --git a/external/tellstick-core/ProtocolGroup.h b/external/tellstick-core/ProtocolGroup.h deleted file mode 100644 index 509c2a3a..00000000 --- a/external/tellstick-core/ProtocolGroup.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ - -#include -#include "service/Protocol.h" - -class ProtocolGroup : public Protocol { -public: - virtual int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ - - - diff --git a/external/tellstick-core/ProtocolHasta.cpp b/external/tellstick-core/ProtocolHasta.cpp deleted file mode 100644 index 786f068b..00000000 --- a/external/tellstick-core/ProtocolHasta.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolHasta.h" -#include -#include -#include -#include "common/Strings.h" - -int ProtocolHasta::methods() const { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; -} - -std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Controller *) { - if (TelldusCore::comparei(model(), L"selflearningv2")) { - return getStringForMethodv2(method); - } - return getStringForMethodv1(method); -} - -std::string ProtocolHasta::getStringForMethodv1(int method) { - int house = this->getIntParameter(L"house", 1, 65536); - int unit = this->getIntParameter(L"unit", 1, 15); - std::string strReturn; - - strReturn.append(1, 164); - strReturn.append(1, 1); - strReturn.append(1, 164); - strReturn.append(1, 1); - strReturn.append(1, 164); - strReturn.append(1, 164); - - strReturn.append(convertByte( (house & 0xFF) )); - strReturn.append(convertByte( (house>>8) & 0xFF )); - - int byte = unit&0x0F; - - if (method == TELLSTICK_UP) { - byte |= 0x00; - - } else if (method == TELLSTICK_DOWN) { - byte |= 0x10; - - } else if (method == TELLSTICK_STOP) { - byte |= 0x50; - - } else if (method == TELLSTICK_LEARN) { - byte |= 0x40; - - } else { - return ""; - } - strReturn.append(convertByte(byte)); - - strReturn.append(convertByte(0x0)); - strReturn.append(convertByte(0x0)); - - // Remove the last pulse - strReturn.erase(strReturn.end()-1, strReturn.end()); - - return strReturn; -} - -std::string ProtocolHasta::convertByte(unsigned char byte) { - std::string retval; - for(int i = 0; i < 8; ++i) { - if (byte & 1) { - retval.append(1, 33); - retval.append(1, 17); - } else { - retval.append(1, 17); - retval.append(1, 33); - } - byte >>= 1; - } - return retval; -} - -std::string ProtocolHasta::getStringForMethodv2(int method) { - int house = this->getIntParameter(L"house", 1, 65536); - int unit = this->getIntParameter(L"unit", 1, 15); - int sum = 0; - std::string strReturn; - strReturn.append(1, 245); - strReturn.append(1, 1); - strReturn.append(1, 245); - strReturn.append(1, 245); - strReturn.append(1, 63); - strReturn.append(1, 1); - strReturn.append(1, 63); - strReturn.append(1, 1); - strReturn.append(1, 35); - strReturn.append(1, 35); - - strReturn.append(convertBytev2( (house>>8) & 0xFF )); - sum = ((house>>8)&0xFF); - strReturn.append(convertBytev2( (house & 0xFF) )); - sum += (house & 0xFF); - - int byte = unit&0x0F; - - if (method == TELLSTICK_UP) { - byte |= 0xC0; - - } else if (method == TELLSTICK_DOWN) { - byte |= 0x10; - - } else if (method == TELLSTICK_STOP) { - byte |= 0x50; - - } else if (method == TELLSTICK_LEARN) { - byte |= 0x40; - - } else { - return ""; - } - strReturn.append(convertBytev2(byte)); - sum += byte; - - strReturn.append(convertBytev2(0x01)); - sum += 0x01; - - int checksum = ((static_cast(sum/256)+1)*256+1) - sum; - strReturn.append(convertBytev2(checksum)); - strReturn.append(1, 63); - strReturn.append(1, 35); - - return strReturn; -} - -std::string ProtocolHasta::convertBytev2(unsigned char byte) { - std::string retval; - for(int i = 0; i < 8; ++i) { - if (byte & 1) { - retval.append(1, 63); - retval.append(1, 35); - } else { - retval.append(1, 35); - retval.append(1, 63); - } - byte >>= 1; - } - return retval; -} - -std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) { - uint64_t allData = dataMsg.getInt64Parameter("data"); - - unsigned int house = 0; - unsigned int unit = 0; - unsigned int method = 0; - std::string model; - std::string methodstring; - - allData >>= 8; - unit = allData & 0xF; - allData >>= 4; - method = allData & 0xF; - allData >>= 4; - if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { - // version1 - house = allData & 0xFFFF; - house = ((house << 8) | (house >> 8)) & 0xFFFF; - model = "selflearning"; - if(method == 0) { - methodstring = "up"; - } else if(method == 1) { - methodstring = "down"; - } else if(method == 5) { - methodstring = "stop"; - } else { - return ""; - } - } else { - // version2 - house = allData & 0xFFFF; - - model = "selflearningv2"; - if(method == 12) { - methodstring = "up"; - } else if(method == 1 || method == 8) { // is method 8 correct? - methodstring = "down"; - } else if(method == 5) { - methodstring = "stop"; - } else { - return ""; - } - } - - if(house < 1 || house > 65535 || unit < 1 || unit > 16) { - // not hasta - return ""; - } - - std::stringstream retString; - retString << "class:command;protocol:hasta;model:" << model << ";house:" << house << ";unit:" << unit << ";method:" << methodstring << ";"; - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolHasta.h b/external/tellstick-core/ProtocolHasta.h deleted file mode 100644 index 7a122bb2..00000000 --- a/external/tellstick-core/ProtocolHasta.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ - -#include -#include "service/ControllerMessage.h" -#include "service/Protocol.h" - -class ProtocolHasta : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(const ControllerMessage &dataMsg); - -protected: - static std::string convertByte(unsigned char byte); - static std::string convertBytev2(unsigned char byte); - std::string getStringForMethodv1(int method); - std::string getStringForMethodv2(int method); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ diff --git a/external/tellstick-core/ProtocolIkea.cpp b/external/tellstick-core/ProtocolIkea.cpp deleted file mode 100644 index 6b96434a..00000000 --- a/external/tellstick-core/ProtocolIkea.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolIkea.h" -#include -#include -#include -#include -#include "common/Strings.h" -#ifdef _WINDOWS -#define strtok_r(s, d, p) strtok_s(s, d, p) -#endif - -int ProtocolIkea::methods() const { - if (TelldusCore::comparei(model(), L"selflearning-switch")) { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; - } - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM; -} - -std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { - const char B1[] = {84, 84, 0}; - const char B0[] = {170, 0}; - - int intSystem = this->getIntParameter(L"system", 1, 16)-1; - int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true"); - std::wstring wstrUnits = this->getStringParameter(L"units", L""); - - if (method == TELLSTICK_TURNON) { - level = 255; - } else if (method == TELLSTICK_TURNOFF) { - level = 0; - } else if (method == TELLSTICK_DIM) { - } else { - return ""; - } - - if (wstrUnits == L"") { - return ""; - } - - std::string strUnits(TelldusCore::wideToString(wstrUnits)); - int intUnits = 0; // Start without any units - - char *tempUnits = new char[strUnits.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); -#else - snprintf(tempUnits, strUnits.size()+1, "%s", strUnits.c_str()); -#endif - - char *saveptr; - char *strToken = strtok_r(tempUnits, ",", &saveptr); - do { - int intUnit = atoi(strToken); - if (intUnit == 10) { - intUnit = 0; - } - intUnits = intUnits | ( 1<<(9-intUnit) ); - } while ( (strToken = strtok_r(NULL, ",", &saveptr)) != NULL ); - - delete[] tempUnits; - - std::string strReturn; - strReturn.append(1, 'S'); - strReturn.append(1, 84); - strReturn.append(1, 84); - strReturn.append(1, 84); - strReturn.append(1, 84); - strReturn.append(1, 84); - strReturn.append(1, 84); - strReturn.append(1, 170); - - std::string strChannels = ""; - int intCode = (intSystem << 10) | intUnits; - int checksum1 = 0; - int checksum2 = 0; - for (int i = 13; i >= 0; --i) { - if ((intCode >> i) & 1) { - strChannels.append(B1); - if (i % 2 == 0) - checksum2++; - else - checksum1++; - } else { - strChannels.append(B0); - } - } - strReturn.append(strChannels); // System + Units - - strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum - strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum - - int intLevel = 0; - if (level <= 12) { - intLevel = 10; // Level 10 is actually off - } else if (level <= 37) { - intLevel = 1; - } else if (level <= 62) { - intLevel = 2; - } else if (level <= 87) { - intLevel = 3; - } else if (level <= 112) { - intLevel = 4; - } else if (level <= 137) { - intLevel = 5; - } else if (level <= 162) { - intLevel = 6; - } else if (level <= 187) { - intLevel = 7; - } else if (level <= 212) { - intLevel = 8; - } else if (level <= 237) { - intLevel = 9; - } else { - intLevel = 0; // Level 0 is actually full on - } - - int intFade = 0; - if (intFadeStyle == 1) { - intFade = 11 << 4; // Smooth - } else { - intFade = 1 << 4; // Instant - } - - intCode = intLevel | intFade; // Concat level and fade - - checksum1 = 0; - checksum2 = 0; - for (int i = 0; i < 6; ++i) { - if ((intCode >> i) & 1) { - strReturn.append(B1); - if (i % 2 == 0) - checksum1++; - else - checksum2++; - } else { - strReturn.append(B0); - } - } - - strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum - strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum - - strReturn.append("+"); - - return strReturn; -} diff --git a/external/tellstick-core/ProtocolIkea.h b/external/tellstick-core/ProtocolIkea.h deleted file mode 100644 index 11a18cbf..00000000 --- a/external/tellstick-core/ProtocolIkea.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ - -#include -#include "service/Protocol.h" - -class ProtocolIkea : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ diff --git a/external/tellstick-core/ProtocolMandolyn.cpp b/external/tellstick-core/ProtocolMandolyn.cpp deleted file mode 100644 index c37555c0..00000000 --- a/external/tellstick-core/ProtocolMandolyn.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolMandolyn.h" -#include -#include -#include -#include -#include "common/Strings.h" - -std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) { - std::string data = dataMsg.getParameter("data"); - uint32_t value = (uint32_t)TelldusCore::hexTo64l(data); - - // parity not used - // bool parity = value & 0x1; - value >>= 1; - - double temp = static_cast(value & 0x7FFF) - static_cast(6400); - temp = temp/128.0; - value >>= 15; - - uint8_t humidity = (value & 0x7F); - value >>= 7; - - // battOk not used - // bool battOk = value & 0x1; - value >>= 3; - - uint8_t channel = (value & 0x3)+1; - value >>= 2; - - uint8_t house = value & 0xF; - - std::stringstream retString; - retString << "class:sensor;protocol:mandolyn;id:" - << house*10+channel - << ";model:temperaturehumidity;" - << "temp:" << std::fixed << std::setprecision(1) << temp - << ";humidity:" << static_cast(humidity) << ";"; - - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolMandolyn.h b/external/tellstick-core/ProtocolMandolyn.h deleted file mode 100644 index 8fcd90a5..00000000 --- a/external/tellstick-core/ProtocolMandolyn.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ - -#include -#include "service/Protocol.h" -#include "service/ControllerMessage.h" - -class ProtocolMandolyn : public Protocol { -public: - static std::string decodeData(const ControllerMessage &dataMsg); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ diff --git a/external/tellstick-core/ProtocolNexa.cpp b/external/tellstick-core/ProtocolNexa.cpp deleted file mode 100644 index 76cc1efc..00000000 --- a/external/tellstick-core/ProtocolNexa.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolNexa.h" -#include -#include -#include -#include "service/TellStick.h" -#include "common/Strings.h" - -int ProtocolNexa::lastArctecCodeSwitchWasTurnOff = 0; // TODO(stefan): always removing first turnon now, make more flexible (waveman too) - -int ProtocolNexa::methods() const { - if (TelldusCore::comparei(model(), L"codeswitch")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); - - } else if (TelldusCore::comparei(model(), L"selflearning-switch")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); - - } else if (TelldusCore::comparei(model(), L"selflearning-dimmer")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); - - } else if (TelldusCore::comparei(model(), L"bell")) { - return TELLSTICK_BELL; - } - return 0; -} - -std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *controller) { - if (TelldusCore::comparei(model(), L"codeswitch")) { - return getStringCodeSwitch(method); - } else if (TelldusCore::comparei(model(), L"bell")) { - return getStringBell(); - } - if ((method == TELLSTICK_TURNON) && TelldusCore::comparei(model(), L"selflearning-dimmer")) { - // Workaround for not letting a dimmer do into "dimming mode" - return getStringSelflearning(TELLSTICK_DIM, 255); - } - if (method == TELLSTICK_LEARN) { - std::string str = getStringSelflearning(TELLSTICK_TURNON, data); - - // Check to see if we are an old TellStick (fw <= 2, batch <= 8) - TellStick *ts = reinterpret_cast(controller); - if (!ts) { - return str; - } - if (ts->pid() == 0x0c30 && ts->firmwareVersion() <= 2) { - // Workaround for the bug in early firmwares - // The TellStick have a fixed pause (max) between two packets. - // It is only correct between the first and second packet. - // It seems faster to send two packes at a time and some - // receivers seems picky about this when learning. - // We also return the last packet so Device::doAction() doesn't - // report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - - str.insert(0, 1, 2); // Repeat two times - str.insert(0, 1, 'R'); - for (int i = 0; i < 5; ++i) { - controller->send(str); - } - } - return str; - } - return getStringSelflearning(method, data); -} - -std::string ProtocolNexa::getStringCodeSwitch(int method) { - std::string strReturn = "S"; - - std::wstring house = getStringParameter(L"house", L"A"); - int intHouse = house[0] - L'A'; - strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1)); - - if (method == TELLSTICK_TURNON) { - strReturn.append("$k$k$kk$$kk$$kk$$k+"); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(this->getOffCode()); - } else { - return ""; - } - return strReturn; -} - -std::string ProtocolNexa::getStringBell() { - std::string strReturn = "S"; - - std::wstring house = getStringParameter(L"house", L"A"); - int intHouse = house[0] - L'A'; - strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append("$kk$$kk$$kk$$k$k"); // Unit 7 - strReturn.append("$kk$$kk$$kk$$kk$$k+"); // Bell - return strReturn; -} - -std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { - int intHouse = getIntParameter(L"house", 1, 67108863); - int intCode = getIntParameter(L"unit", 1, 16)-1; - return getStringSelflearningForCode(intHouse, intCode, method, level); -} - -std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode, int method, unsigned char level) { - const unsigned char START[] = {'T', 127, 255, 24, 1, 0}; - // const char START[] = {'T',130,255,26,24,0}; - - std::string strMessage(reinterpret_cast(START)); - strMessage.append(1, (method == TELLSTICK_DIM ? 147 : 132)); // Number of pulses - - std::string m; - for (int i = 25; i >= 0; --i) { - m.append( intHouse & 1 << i ? "10" : "01" ); - } - m.append("01"); // Group - - // On/off - if (method == TELLSTICK_DIM) { - m.append("00"); - } else if (method == TELLSTICK_TURNOFF) { - m.append("01"); - } else if (method == TELLSTICK_TURNON) { - m.append("10"); - } else { - return ""; - } - - for (int i = 3; i >= 0; --i) { - m.append( intCode & 1 << i ? "10" : "01" ); - } - - if (method == TELLSTICK_DIM) { - unsigned char newLevel = level/16; - for (int i = 3; i >= 0; --i) { - m.append(newLevel & 1 << i ? "10" : "01"); - } - } - - // The number of data is odd. - // Add this to make it even, otherwise the following loop will not work - m.append("0"); - - unsigned char code = 9; // b1001, startcode - for (unsigned int i = 0; i < m.length(); ++i) { - code <<= 4; - if (m[i] == '1') { - code |= 8; // b1000 - } else { - code |= 10; // b1010 - // code |= 11; //b1011 - } - if (i % 2 == 0) { - strMessage.append(1, code); - code = 0; - } - } - strMessage.append("+"); - -// for( int i = 0; i < strMessage.length(); ++i ) { -// printf("%i,", (unsigned char)strMessage[i]); -// } -// printf("\n"); - return strMessage; -} - -std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) { - uint64_t allData = dataMsg.getInt64Parameter("data"); - - if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { - // selflearning - return decodeDataSelfLearning(allData); - } else { - // codeswitch - return decodeDataCodeSwitch(allData); - } -} - -std::string ProtocolNexa::decodeDataSelfLearning(uint64_t allData) { - unsigned int house = 0; - unsigned int unit = 0; - unsigned int group = 0; - unsigned int method = 0; - - house = allData & 0xFFFFFFC0; - house >>= 6; - - group = allData & 0x20; - group >>= 5; - - method = allData & 0x10; - method >>= 4; - - unit = allData & 0xF; - unit++; - - if(house < 1 || house > 67108863 || unit < 1 || unit > 16) { - // not arctech selflearning - return ""; - } - - std::stringstream retString; - retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:"; - if(method == 1) { - retString << "turnon;"; - } else if(method == 0) { - retString << "turnoff;"; - } else { - // not arctech selflearning - return ""; - } - - return retString.str(); -} - -std::string ProtocolNexa::decodeDataCodeSwitch(uint64_t allData) { - unsigned int house = 0; - unsigned int unit = 0; - unsigned int method = 0; - - method = allData & 0xF00; - method >>= 8; - - unit = allData & 0xF0; - unit >>= 4; - unit++; - - house = allData & 0xF; - - if(house > 16 || unit < 1 || unit > 16) { - // not arctech codeswitch - return ""; - } - - house = house + 'A'; // house from A to P - - if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) { - lastArctecCodeSwitchWasTurnOff = 0; - return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - // one turnon/bell, but it's better than the alternative... - } - - if(method == 6) { - lastArctecCodeSwitchWasTurnOff = 1; - } - - std::stringstream retString; - retString << "class:command;protocol:arctech;model:codeswitch;house:" << static_cast(house); - - if(method == 6) { - retString << ";unit:" << unit << ";method:turnoff;"; - } else if(method == 14) { - retString << ";unit:" << unit << ";method:turnon;"; - } else if(method == 15) { - retString << ";method:bell;"; - } else { - // not arctech codeswitch - return ""; - } - - return retString.str(); -} - -std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { - std::string strReturn = ""; - for( int i = 0; i < 4; ++i ) { - if (intCode & 1) { // Convert 1 - strReturn.append("$kk$"); - } else { // Convert 0 - strReturn.append("$k$k"); - } - intCode >>= 1; - } - return strReturn; -} - -std::string ProtocolNexa::getOffCode() const { - return "$k$k$kk$$kk$$k$k$k+"; -} diff --git a/external/tellstick-core/ProtocolNexa.h b/external/tellstick-core/ProtocolNexa.h deleted file mode 100644 index 82809973..00000000 --- a/external/tellstick-core/ProtocolNexa.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ - -#ifdef _MSC_VER -typedef unsigned __int64 uint64_t; -#else -#include -#endif -#include -#include "service/ControllerMessage.h" -#include "service/Device.h" - -class ProtocolNexa : public Protocol { -public: - virtual int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(const ControllerMessage &dataMsg); - -protected: - std::string getStringSelflearning(int method, unsigned char data); - std::string getStringCodeSwitch(int method); - std::string getStringBell(); - virtual std::string getOffCode() const; - static std::string getCodeSwitchTuple(int code); - static std::string getStringSelflearningForCode(int house, int unit, int method, unsigned char data); - -private: - static int lastArctecCodeSwitchWasTurnOff; - static std::string decodeDataCodeSwitch(uint64_t allData); - static std::string decodeDataSelfLearning(uint64_t allData); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ diff --git a/external/tellstick-core/ProtocolOregon.cpp b/external/tellstick-core/ProtocolOregon.cpp deleted file mode 100644 index 3fcfe6dc..00000000 --- a/external/tellstick-core/ProtocolOregon.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolOregon.h" -#include -#include -#include -#include -#include "common/Strings.h" - -std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) { - std::string data = dataMsg.getParameter("data"); - - std::wstring model = dataMsg.model(); - if (model.compare(L"0xEA4C") == 0) { - return decodeEA4C(data); - } else if (model.compare(L"0x1A2D") == 0) { - return decode1A2D(data); - } else if (model.compare(L"0xF824") == 0) { - return decodeF824(data); - } else if (model.compare(L"0x1984") == 0 || model.compare(L"0x1994") == 0) { - return decode1984(data, model); - } else if (model.compare(L"0x2914") == 0) { - return decode2914(data); - } else if (model.compare(L"0xC844") == 0 || model.compare(L"0xEC40") == 0) { - // C844 - pool thermometer - return decodeC844(data, model); - } - - return ""; -} - -std::string ProtocolOregon::decodeEA4C(const std::string &data) { - uint64_t value = TelldusCore::hexTo64l(data); - - uint8_t checksum = 0xE + 0xA + 0x4 + 0xC; - checksum -= (value & 0xF) * 0x10; - checksum -= 0xA; - value >>= 8; - - uint8_t checksumw = (value >> 4) & 0xF; - bool neg = value & (1 << 3); - int hundred = value & 3; - checksum += (value & 0xF); - value >>= 8; - - uint8_t temp2 = value & 0xF; - uint8_t temp1 = (value >> 4) & 0xF; - checksum += temp2 + temp1; - value >>= 8; - - uint8_t temp3 = (value >> 4) & 0xF; - checksum += (value & 0xF) + temp3; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t address = value & 0xFF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - // channel not used - // uint8_t channel = (value >> 4) & 0x7; - - if (checksum != checksumw) { - return ""; - } - - double temperature = ((hundred * 1000) + (temp1 * 100) + (temp2 * 10) + temp3)/10.0; - if (neg) { - temperature = -temperature; - } - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:EA4C;id:" << static_cast(address) - << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; - - return retString.str(); -} - -std::string ProtocolOregon::decode1984(const std::string &data, const std::wstring &model) { - // wind - uint64_t value = TelldusCore::hexTo64l(data); - - uint8_t crcCheck = value & 0xF; // PROBABLY crc - value >>= 4; - uint8_t messageChecksum1 = value & 0xF; - value >>= 4; - uint8_t messageChecksum2 = value & 0xF; - - value >>= 4; - uint8_t avg1 = value & 0xF; - value >>= 4; - uint8_t avg2 = value & 0xF; - value >>= 4; - uint8_t avg3 = value & 0xF; - value >>= 4; - uint8_t gust1 = value & 0xF; - value >>= 4; - uint8_t gust2 = value & 0xF; - value >>= 4; - uint8_t gust3 = value & 0xF; - value >>= 4; - uint8_t unknown1 = value & 0xF; - value >>= 4; - uint8_t unknown2 = value & 0xF; - value >>= 4; - uint8_t direction = value & 0xF; - - value >>= 4; - uint8_t battery = value & 0xF; // PROBABLY battery - value >>= 4; - uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); - uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); - value >>= 8; - uint8_t channel = value & 0xF; - checksum += unknown1 + unknown2 + avg1 + avg2 + avg3 + gust1 + gust2 + gust3 + direction + battery + channel; - - if (model.compare(L"0x1984") == 0) { - checksum += 0x1 + 0x9 + 0x8 + 0x4; - } else { - checksum += 0x1 + 0x9 + 0x9 + 0x4; - } - - if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { - // checksum error - return ""; - } - - - double avg = ((avg1 * 100) + (avg2 * 10) + avg3)/10.0; - double gust = ((gust1 * 100) + (gust2 * 10) + gust3)/10.0; - float directiondegree = 22.5 * direction; - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:1984;id:" << static_cast(rollingcode) - << ";winddirection:" << directiondegree - << ";windaverage:" << std::fixed << std::setprecision(1) << avg - << ";windgust:" << std::fixed << std::setprecision(1) << gust << ";"; - - return retString.str(); -} - -std::string ProtocolOregon::decode1A2D(const std::string &data) { - uint64_t value = TelldusCore::hexTo64l(data); - // checksum2 not used yet - // uint8_t checksum2 = value & 0xFF; - value >>= 8; - uint8_t checksum1 = value & 0xFF; - value >>= 8; - - uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); - uint8_t hum1 = value & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t neg = value & (1 << 3); - uint8_t hum2 = (value >> 4) & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t temp2 = value & 0xF; - uint8_t temp1 = (value >> 4) & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t temp3 = (value >> 4) & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t address = value & 0xFF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - // channel not used - // uint8_t channel = (value >> 4) & 0x7; - - checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA; - - // TODO(micke): Find out how checksum2 works - if (checksum != checksum1) { - return ""; - } - - double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; - if (neg) { - temperature = -temperature; - } - int humidity = (hum1 * 10.0) + hum2; - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:1A2D;id:" << static_cast(address) - << ";temp:" << std::fixed << std::setprecision(1) << temperature - << ";humidity:" << humidity << ";"; - - return retString.str(); -} - -std::string ProtocolOregon::decode2914(const std::string &data) { - // rain - uint64_t value = TelldusCore::hexTo64l(data); - - uint8_t messageChecksum1 = value & 0xF; - value >>= 4; - uint8_t messageChecksum2 = value & 0xF; - - value >>= 4; - uint8_t totRain1 = value & 0xF; - value >>= 4; - uint8_t totRain2 = value & 0xF; - value >>= 4; - uint8_t totRain3 = value & 0xF; - value >>= 4; - uint8_t totRain4 = value & 0xF; - value >>= 4; - uint8_t totRain5 = value & 0xF; - value >>= 4; - uint8_t totRain6 = value & 0xF; - value >>= 4; - uint8_t rainRate1 = value & 0xF; - value >>= 4; - uint8_t rainRate2 = value & 0xF; - value >>= 4; - uint8_t rainRate3 = value & 0xF; - value >>= 4; - uint8_t rainRate4 = value & 0xF; - - value >>= 4; - uint8_t battery = value & 0xF; // PROBABLY battery - value >>= 4; - uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); - uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); - value >>= 8; - uint8_t channel = value & 0xF; - checksum += totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 + rainRate1 + rainRate2 + rainRate3 + rainRate4 + battery + channel + 0x2 + 0x9 + 0x1 + 0x4; - - if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { - // checksum error - return ""; - } - - double totRain = ((totRain1 * 100000) + (totRain2 * 10000) + (totRain3 * 1000) + (totRain4 * 100) + (totRain5 * 10) + totRain6)/1000.0*25.4; - double rainRate = ((rainRate1 * 1000) + (rainRate2 * 100) + (rainRate3 * 10) + rainRate4)/100.0*25.4; - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:2914;id:" << static_cast(rollingcode) - << ";raintotal:" << std::fixed << std::setprecision(1) << totRain - << ";rainrate:" << std::fixed << std::setprecision(1) << rainRate << ";"; - return retString.str(); -} - -std::string ProtocolOregon::decodeF824(const std::string &data) { - uint64_t value = TelldusCore::hexTo64l(data); - - uint8_t crcCheck = value & 0xF; // PROBABLY crc - value >>= 4; - uint8_t messageChecksum1 = value & 0xF; - value >>= 4; - uint8_t messageChecksum2 = value & 0xF; - value >>= 4; - uint8_t unknown = value & 0xF; - value >>= 4; - uint8_t hum1 = value & 0xF; - value >>= 4; - uint8_t hum2 = value & 0xF; - value >>= 4; - uint8_t neg = value & 0xF; - value >>= 4; - uint8_t temp1 = value & 0xF; - value >>= 4; - uint8_t temp2 = value & 0xF; - value >>= 4; - uint8_t temp3 = value & 0xF; - value >>= 4; - uint8_t battery = value & 0xF; // PROBABLY battery - value >>= 4; - uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); - uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); - value >>= 8; - uint8_t channel = value & 0xF; - checksum += unknown + hum1 + hum2 + neg + temp1 + temp2 + temp3 + battery + channel + 0xF + 0x8 + 0x2 + 0x4; - - if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { - // checksum error - return ""; - } - - double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; - if (neg) { - temperature = -temperature; - } - int humidity = (hum1 * 10.0) + hum2; - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:F824;id:" << static_cast(rollingcode) - << ";temp:" << std::fixed << std::setprecision(1) << temperature - << ";humidity:" << humidity << ";"; - - return retString.str(); -} - -std::string ProtocolOregon::decodeC844(const std::string &data, const std::wstring &model) { - uint64_t value = TelldusCore::hexTo64l(data); - - uint8_t messageChecksum1 = value & 0xF; - value >>= 4; - uint8_t messageChecksum2 = value & 0xF; - value >>= 4; - uint8_t neg = value & 0xF; - value >>= 4; - uint8_t temp1 = value & 0xF; - value >>= 4; - uint8_t temp2 = value & 0xF; - value >>= 4; - uint8_t temp3 = value & 0xF; - value >>= 4; - uint8_t battery = value & 0xF; // PROBABLY battery - value >>= 4; - uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); - uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); - value >>= 8; - uint8_t channel = value & 0xF; - checksum += neg + temp1 + temp2 + temp3 + battery + channel; - - if (model.compare(L"0xC844") == 0) { - checksum += 0xC + 0x8 + 0x4 + 0x4; - } else { - checksum += 0xE + 0xC + 0x4 + 0x0; - } - - if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { - // checksum error - return ""; - } - - double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; - if (neg) { - temperature = -temperature; - } - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:C844;id:" << static_cast(rollingcode) - << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolOregon.h b/external/tellstick-core/ProtocolOregon.h deleted file mode 100644 index cc68fe86..00000000 --- a/external/tellstick-core/ProtocolOregon.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ - -#include -#include "service/Protocol.h" -#include "service/ControllerMessage.h" - -class ProtocolOregon : public Protocol { -public: - static std::string decodeData(const ControllerMessage &dataMsg); - -protected: - static std::string decodeEA4C(const std::string &data); - static std::string decode1A2D(const std::string &data); - static std::string decodeF824(const std::string &data); - static std::string decode1984(const std::string &data, const std::wstring &model); - static std::string decode2914(const std::string &data); - static std::string decodeC844(const std::string &data, const std::wstring &model); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ diff --git a/external/tellstick-core/ProtocolRisingSun.cpp b/external/tellstick-core/ProtocolRisingSun.cpp deleted file mode 100644 index c4e9ae0c..00000000 --- a/external/tellstick-core/ProtocolRisingSun.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolRisingSun.h" -#include -#include "common/Strings.h" - -int ProtocolRisingSun::methods() const { - if (TelldusCore::comparei(model(), L"selflearning")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); - } - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) { - if (TelldusCore::comparei(model(), L"selflearning")) { - return getStringSelflearning(method); - } - return getStringCodeSwitch(method); -} - -std::string ProtocolRisingSun::getStringSelflearning(int method) { - int intHouse = this->getIntParameter(L"house", 1, 33554432)-1; - int intCode = this->getIntParameter(L"code", 1, 16)-1; - - const char code_on[][7] = { - "110110", "001110", "100110", "010110", - "111001", "000101", "101001", "011001", - "110000", "001000", "100000", "010000", - "111100", "000010", "101100", "011100" - }; - const char code_off[][7] = { - "111110", "000001", "101110", "011110", - "110101", "001101", "100101", "010101", - "111000", "000100", "101000", "011000", - "110010", "001010", "100010", "010010" - }; - const char l = 120; - const char s = 51; - - std::string strCode = "10"; - int code = intCode; - code = (code < 0 ? 0 : code); - code = (code > 15 ? 15 : code); - if (method == TELLSTICK_TURNON) { - strCode.append(code_on[code]); - } else if (method == TELLSTICK_TURNOFF) { - strCode.append(code_off[code]); - } else if (method == TELLSTICK_LEARN) { - strCode.append(code_on[code]); - } else { - return ""; - } - - int house = intHouse; - for(int i = 0; i < 25; ++i) { - if (house & 1) { - strCode.append(1, '1'); - } else { - strCode.append(1, '0'); - } - house >>= 1; - } - - std::string strReturn; - for(unsigned int i = 0; i < strCode.length(); ++i) { - if (strCode[i] == '1') { - strReturn.append(1, l); - strReturn.append(1, s); - } else { - strReturn.append(1, s); - strReturn.append(1, l); - } - } - - std::string prefix = "P"; - prefix.append(1, 5); - if (method == TELLSTICK_LEARN) { - prefix.append("R"); - prefix.append( 1, 50 ); - } - prefix.append("S"); - strReturn.insert(0, prefix); - strReturn.append(1, '+'); - return strReturn; -} - -std::string ProtocolRisingSun::getStringCodeSwitch(int method) { - std::string strReturn = "S.e"; - strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4)-1)); - strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4)-1)); - if (method == TELLSTICK_TURNON) { - strReturn.append("e..ee..ee..ee..e+"); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append("e..ee..ee..e.e.e+"); - } else { - return ""; - } - return strReturn; -} - -std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) { - std::string strReturn = ""; - for(int i = 0; i < 4; ++i) { - if (i == intToConvert) { - strReturn.append( ".e.e" ); - } else { - strReturn.append( "e..e" ); - } - } - return strReturn; -} diff --git a/external/tellstick-core/ProtocolRisingSun.h b/external/tellstick-core/ProtocolRisingSun.h deleted file mode 100644 index ef6262e5..00000000 --- a/external/tellstick-core/ProtocolRisingSun.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ - -#include -#include "service/Protocol.h" - -class ProtocolRisingSun : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - -protected: - std::string getStringSelflearning(int method); - std::string getStringCodeSwitch(int method); - static std::string getCodeSwitchTuple(int code); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ diff --git a/external/tellstick-core/ProtocolSartano.cpp b/external/tellstick-core/ProtocolSartano.cpp deleted file mode 100644 index 0b33f354..00000000 --- a/external/tellstick-core/ProtocolSartano.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolSartano.h" -#ifdef _MSC_VER -typedef unsigned __int16 uint16_t; -#else -#include -#endif -#include -#include -#include - -int ProtocolSartano::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) { - std::wstring strCode = this->getStringParameter(L"code", L""); - return getStringForCode(strCode, method); -} - -std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int method) { - std::string strReturn("S"); - - for (size_t i = 0; i < strCode.length(); ++i) { - if (strCode[i] == L'1') { - strReturn.append("$k$k"); - } else { - strReturn.append("$kk$"); - } - } - - if (method == TELLSTICK_TURNON) { - strReturn.append("$k$k$kk$$k+"); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append("$kk$$k$k$k+"); - } else { - return ""; - } - - return strReturn; -} - -std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { - uint64_t allDataIn; - uint16_t allData = 0; - unsigned int code = 0; - unsigned int method1 = 0; - unsigned int method2 = 0; - unsigned int method = 0; - - allDataIn = dataMsg.getInt64Parameter("data"); - - uint16_t mask = (1<<11); - for(int i = 0; i < 12; ++i) { - allData >>= 1; - if((allDataIn & mask) == 0) { - allData |= (1<<11); - } - mask >>= 1; - } - - code = allData & 0xFFC; - code >>= 2; - - method1 = allData & 0x2; - method1 >>= 1; - - method2 = allData & 0x1; - - if(method1 == 0 && method2 == 1) { - method = 0; // off - } else if(method1 == 1 && method2 == 0) { - method = 1; // on - } else { - return ""; - } - - if(code > 1023) { - // not sartano - return ""; - } - - std::stringstream retString; - retString << "class:command;protocol:sartano;model:codeswitch;code:"; - mask = (1<<9); - for(int i = 0; i < 10; i++) { - if((code & mask) != 0) { - retString << 1; - } else { - retString << 0; - } - mask >>= 1; - } - retString << ";method:"; - - if(method == 0) { - retString << "turnoff;"; - } else { - retString << "turnon;"; - } - - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolSartano.h b/external/tellstick-core/ProtocolSartano.h deleted file mode 100644 index d644a0e8..00000000 --- a/external/tellstick-core/ProtocolSartano.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ - -#include -#include "service/Protocol.h" -#include "service/ControllerMessage.h" - -class ProtocolSartano : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(const ControllerMessage &dataMsg); - -protected: - std::string getStringForCode(const std::wstring &code, int method); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ diff --git a/external/tellstick-core/ProtocolScene.cpp b/external/tellstick-core/ProtocolScene.cpp deleted file mode 100644 index 24ae5318..00000000 --- a/external/tellstick-core/ProtocolScene.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolScene.h" -#include - -int ProtocolScene::methods() const { - return TELLSTICK_EXECUTE; -} - -std::string ProtocolScene::getStringForMethod(int method, unsigned char data, Controller *) { - return ""; -} diff --git a/external/tellstick-core/ProtocolScene.h b/external/tellstick-core/ProtocolScene.h deleted file mode 100644 index 87f80afe..00000000 --- a/external/tellstick-core/ProtocolScene.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ - -#include -#include "service/Protocol.h" - -class ProtocolScene : public Protocol { -public: - virtual int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ - - - diff --git a/external/tellstick-core/ProtocolSilvanChip.cpp b/external/tellstick-core/ProtocolSilvanChip.cpp deleted file mode 100644 index ddc20068..00000000 --- a/external/tellstick-core/ProtocolSilvanChip.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolSilvanChip.h" -#include -#include "common/Strings.h" - -int ProtocolSilvanChip::methods() const { - if (TelldusCore::comparei(model(), L"kp100")) { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; - } else if (TelldusCore::comparei(model(), L"ecosavers")) { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; - } else if (TelldusCore::comparei(model(), L"displaymatic")) { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; - } - return 0; -} - -std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { - if (TelldusCore::comparei(model(), L"kp100")) { - std::string preamble; - preamble.append(1, 100); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 100); - - const std::string one = "\xFF\x1\x2E\x2E"; - const std::string zero = "\x2E\xFF\x1\x2E"; - int button = 0; - if (method == TELLSTICK_UP) { - button = 2; - } else if (method == TELLSTICK_DOWN) { - button = 8; - } else if (method == TELLSTICK_STOP) { - button = 4; - } else if (method == TELLSTICK_LEARN) { - button = 1; - } else { - return ""; - } - return this->getString(preamble, one, zero, button); - } else if (TelldusCore::comparei(model(), L"displaymatic")) { - std::string preamble; - preamble.append(1, 0x25); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 0x25); - const std::string one = "\x69\25"; - const std::string zero = "\x25\x69"; - int button = 0; - if (method == TELLSTICK_UP) { - button = 1; - } else if (method == TELLSTICK_DOWN) { - button = 4; - } else if (method == TELLSTICK_STOP) { - button = 2; - } - return this->getString(preamble, one, zero, button); - } else if (TelldusCore::comparei(model(), L"ecosavers")) { - std::string preamble; - preamble.append(1, 0x25); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 0x25); - const std::string one = "\x69\25"; - const std::string zero = "\x25\x69"; - int intUnit = this->getIntParameter(L"unit", 1, 4); - int button = 0; - if (intUnit == 1) { - button = 7; - } else if (intUnit == 2) { - button = 3; - } else if (intUnit == 3) { - button = 5; - } else if (intUnit == 4) { - button = 6; - } - - if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { - button |= 8; - } - return this->getString(preamble, one, zero, button); - } - return ""; -} - -std::string ProtocolSilvanChip::getString(const std::string &preamble, const std::string &one, const std::string &zero, int button) { - int intHouse = this->getIntParameter(L"house", 1, 1048575); - std::string strReturn = preamble; - - for( int i = 19; i >= 0; --i ) { - if (intHouse & (1 << i)) { - strReturn.append(one); - } else { - strReturn.append(zero); - } - } - - for( int i = 3; i >= 0; --i) { - if (button & (1 << i)) { - strReturn.append(one); - } else { - strReturn.append(zero); - } - } - - strReturn.append(zero); - return strReturn; -} diff --git a/external/tellstick-core/ProtocolSilvanChip.h b/external/tellstick-core/ProtocolSilvanChip.h deleted file mode 100644 index 188a2d4a..00000000 --- a/external/tellstick-core/ProtocolSilvanChip.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ - -#include -#include "service/Protocol.h" - -class ProtocolSilvanChip : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - -protected: - virtual std::string getString(const std::string &preamble, const std::string &one, const std::string &zero, int button); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ diff --git a/external/tellstick-core/ProtocolUpm.cpp b/external/tellstick-core/ProtocolUpm.cpp deleted file mode 100644 index 4e70b797..00000000 --- a/external/tellstick-core/ProtocolUpm.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolUpm.h" -#include - -int ProtocolUpm::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; -} - -std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) { - const char S = ';'; - const char L = '~'; - const char START[] = {S, 0}; - const char B1[] = {L, S, 0}; - const char B0[] = {S, L, 0}; - // const char BON[] = {S,L,L,S,0}; - // const char BOFF[] = {S,L,S,L,0}; - - int intUnit = this->getIntParameter(L"unit", 1, 4)-1; - std::string strReturn; - - int code = this->getIntParameter(L"house", 0, 4095); - for( size_t i = 0; i < 12; ++i ) { - if (code & 1) { - strReturn.insert(0, B1); - } else { - strReturn.insert(0, B0); - } - code >>= 1; - } - strReturn.insert(0, START); // Startcode, first - - code = 0; - if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { - code += 2; - } else if (method != TELLSTICK_TURNOFF) { - return ""; - } - code <<= 2; - code += intUnit; - - int check1 = 0, check2 = 0; - for( size_t i = 0; i < 6; ++i ) { - if (code & 1) { - if (i % 2 == 0) { - check1++; - } else { - check2++; - } - } - if (code & 1) { - strReturn.append(B1); - } else { - strReturn.append(B0); - } - code >>= 1; - } - - if (check1 % 2 == 0) { - strReturn.append(B0); - } else { - strReturn.append(B1); - } - if (check2 % 2 == 0) { - strReturn.append(B0); - } else { - strReturn.append(B1); - } - - strReturn.insert(0, "S"); - strReturn.append("+"); - return strReturn; -} - diff --git a/external/tellstick-core/ProtocolUpm.h b/external/tellstick-core/ProtocolUpm.h deleted file mode 100644 index 9283a408..00000000 --- a/external/tellstick-core/ProtocolUpm.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ - -#include -#include "service/Protocol.h" - -class ProtocolUpm : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ diff --git a/external/tellstick-core/ProtocolWaveman.cpp b/external/tellstick-core/ProtocolWaveman.cpp deleted file mode 100644 index 9684934b..00000000 --- a/external/tellstick-core/ProtocolWaveman.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolWaveman.h" -#ifdef _MSC_VER -#else -#include -#endif -#include -#include -#include - -int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff = 0; - -int ProtocolWaveman::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) { - return getStringCodeSwitch(method); -} - -std::string ProtocolWaveman::getOffCode() const { - return "$k$k$k$k$k$k$k$k$k+"; -} - -std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) { - uint64_t allData = 0; - unsigned int house = 0; - unsigned int unit = 0; - unsigned int method = 0; - - allData = dataMsg.getInt64Parameter("data"); - - method = allData & 0xF00; - method >>= 8; - - unit = allData & 0xF0; - unit >>= 4; - unit++; - - house = allData & 0xF; - - if(house > 16 || unit < 1 || unit > 16) { - // not waveman - return ""; - } - - house = house + 'A'; // house from A to P - - if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) { - lastArctecCodeSwitchWasTurnOff = 0; - return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - // one turnon/bell, but it's better than the alternative... - } - - if(method == 6) { - lastArctecCodeSwitchWasTurnOff = 1; - } - - std::stringstream retString; - retString << "class:command;protocol:waveman;model:codeswitch;house:" << static_cast(house); - - if(method == 0) { - retString << ";unit:" << unit << ";method:turnoff;"; - } else if(method == 14) { - retString << ";unit:" << unit << ";method:turnon;"; - } else { - // not waveman - return ""; - } - - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolWaveman.h b/external/tellstick-core/ProtocolWaveman.h deleted file mode 100644 index a6feb394..00000000 --- a/external/tellstick-core/ProtocolWaveman.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ - -#include -#include "service/ProtocolNexa.h" - -class ProtocolWaveman : public ProtocolNexa { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(const ControllerMessage &dataMsg); - -protected: - virtual std::string getOffCode() const; - -private: - static int lastArctecCodeSwitchWasTurnOff; -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ diff --git a/external/tellstick-core/ProtocolX10.cpp b/external/tellstick-core/ProtocolX10.cpp deleted file mode 100644 index c46d5a39..00000000 --- a/external/tellstick-core/ProtocolX10.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "service/ProtocolX10.h" -#ifdef _MSC_VER -#else -#include -#endif -#include -#include -#include - -const unsigned char HOUSES[] = {6, 0xE, 2, 0xA, 1, 9, 5, 0xD, 7, 0xF, 3, 0xB, 0, 8, 4, 0xC}; - -int ProtocolX10::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) { - const unsigned char S = 59, L = 169; - const char B0[] = {S, S, 0}; - const char B1[] = {S, L, 0}; - const unsigned char START_CODE[] = {'S', 255, 1, 255, 1, 255, 1, 100, 255, 1, 180, 0}; - const unsigned char STOP_CODE[] = {S, 0}; - - std::string strReturn = reinterpret_cast(START_CODE); - std::string strComplement = ""; - - std::wstring strHouse = getStringParameter(L"house", L"A"); - int intHouse = strHouse[0] - L'A'; - if (intHouse < 0) { - intHouse = 0; - } else if (intHouse > 15) { - intHouse = 15; - } - // Translate it - intHouse = HOUSES[intHouse]; - int intCode = getIntParameter(L"unit", 1, 16)-1; - - for( int i = 0; i < 4; ++i ) { - if (intHouse & 1) { - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - intHouse >>= 1; - } - strReturn.append( B0 ); - strComplement.append( B1 ); - - if (intCode >= 8) { - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - strReturn.append( B0 ); - strComplement.append( B1 ); - strReturn.append( B0 ); - strComplement.append( B1 ); - - strReturn.append( strComplement ); - strComplement = ""; - - strReturn.append( B0 ); - strComplement.append( B1 ); - - if (intCode >> 2 & 1) { // Bit 2 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - if (method == TELLSTICK_TURNON) { - strReturn.append(B0); - strComplement.append(B1); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(B1); - strComplement.append(B0); - } else { - return ""; - } - - if (intCode & 1) { // Bit 0 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - if (intCode >> 1 & 1) { // Bit 1 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - for( int i = 0; i < 3; ++i ) { - strReturn.append( B0 ); - strComplement.append( B1 ); - } - - strReturn.append( strComplement ); - strReturn.append( reinterpret_cast(STOP_CODE) ); - strReturn.append("+"); - return strReturn; -} - -std::string ProtocolX10::decodeData(const ControllerMessage& dataMsg) { - uint64_t intData = 0, currentBit = 31; - bool method = 0; - - intData = dataMsg.getInt64Parameter("data"); - - int unit = 0; - int rawHouse = 0; - for(int i = 0; i < 4; ++i) { - rawHouse >>= 1; - if (checkBit(intData, currentBit--)) { - rawHouse |= 0x8; - } - } - - if (checkBit(intData, currentBit--) != 0) { - return ""; - } - - if (checkBit(intData, currentBit--)) { - unit |= (1<<3); - } - - if (checkBit(intData, currentBit--)) { - return ""; - } - if (checkBit(intData, currentBit--)) { - return ""; - } - - currentBit = 14; - - if (checkBit(intData, currentBit--)) { - unit |= (1<<2); - } - if (checkBit(intData, currentBit--)) { - method = 1; - } - if (checkBit(intData, currentBit--)) { - unit |= (1<<0); - } - if (checkBit(intData, currentBit--)) { - unit |= (1<<1); - } - - int intHouse = 0; - for(int i = 0; i < 16; ++i) { - if (HOUSES[i] == rawHouse) { - intHouse = i; - break; - } - } - - std::stringstream retString; - retString << "class:command;protocol:x10;model:codeswitch;"; - retString << "house:" << static_cast('A' + intHouse); - retString << ";unit:" << unit+1; - retString << ";method:"; - if (method == 0) { - retString << "turnon;"; - } else { - retString << "turnoff;"; - } - - return retString.str(); -} diff --git a/external/tellstick-core/ProtocolX10.h b/external/tellstick-core/ProtocolX10.h deleted file mode 100644 index c8cf8422..00000000 --- a/external/tellstick-core/ProtocolX10.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ - -#include -#include "service/Protocol.h" -#include "service/ControllerMessage.h" - -class ProtocolX10 : public Protocol { -public: - int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - - static std::string decodeData(const ControllerMessage &dataMsg); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ diff --git a/external/tellstick-core/ProtocolYidong.cpp b/external/tellstick-core/ProtocolYidong.cpp deleted file mode 100644 index 61b9f33f..00000000 --- a/external/tellstick-core/ProtocolYidong.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include -#include "service/ProtocolYidong.h" - -std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { - int intCode = this->getIntParameter(L"unit", 1, 4); - std::wstring strCode = L"111"; - - switch(intCode) { - case 1: - strCode.append(L"0010"); - break; - case 2: - strCode.append(L"0001"); - break; - case 3: - strCode.append(L"0100"); - break; - case 4: - strCode.append(L"1000"); - break; - } - - strCode.append(L"110"); - return getStringForCode(strCode, method); -} diff --git a/external/tellstick-core/ProtocolYidong.h b/external/tellstick-core/ProtocolYidong.h deleted file mode 100644 index c6b628c4..00000000 --- a/external/tellstick-core/ProtocolYidong.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ -#define TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ - -#include -#include "service/ProtocolSartano.h" - -class ProtocolYidong : public ProtocolSartano { -public: - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); -}; - -#endif // TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ diff --git a/external/tellstick-core/README.txt b/external/tellstick-core/README.txt deleted file mode 100644 index dd80b5bf..00000000 --- a/external/tellstick-core/README.txt +++ /dev/null @@ -1,30 +0,0 @@ -This is Telldus Core version {version} - -Telldus Core is the driver and tools for controlling a Telldus Technologies -TellStick. It does not containing any GUI tools which makes it suitable for -server use. - - -INSTALLING Telldus Core - -On Windows, if you want to install the precompiles binary packages, simply -launch the package and follow the instructions in the installation wizard. - -If you have a source package (a .tar.gz file), follow the instruction in the -INSTALL file. - - -CONFIGURATION AND TOOLS - -Once Telldus Core is installed, we suggest that you start by adding the devices -you want to control. - -On Windows, this is done by installing TelldusCenter. On Linux it's done by -editing the file /etc/tellstick.conf directly, or in TelldusCenter. - -Telldus Core installs the tool tdtool for controlling devices with TellStick. -Have a look in the man page for a description how to use it: - - man tdtool - -TellStick is a trademark of Telldus Technologies AB diff --git a/external/tellstick-driver/SerialDriver_Windows/Static/amd64/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows/Static/amd64/ftd2xx.lib deleted file mode 100644 index 11509d69..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/Static/amd64/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/Static/i386/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows/Static/i386/ftd2xx.lib deleted file mode 100644 index 3ff1d541..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/Static/i386/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftbusui.dll b/external/tellstick-driver/SerialDriver_Windows/amd64/ftbusui.dll deleted file mode 100644 index 398a1d82..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftbusui.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftcserco.dll b/external/tellstick-driver/SerialDriver_Windows/amd64/ftcserco.dll deleted file mode 100644 index 317d6a82..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftcserco.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows/amd64/ftd2xx.lib deleted file mode 100644 index bb1669cd..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftd2xx64.dll b/external/tellstick-driver/SerialDriver_Windows/amd64/ftd2xx64.dll deleted file mode 100644 index 7ebc3b67..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftd2xx64.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftdibus.sys b/external/tellstick-driver/SerialDriver_Windows/amd64/ftdibus.sys deleted file mode 100644 index 208d6f14..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftdibus.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftlang.dll b/external/tellstick-driver/SerialDriver_Windows/amd64/ftlang.dll deleted file mode 100644 index 8b9ae95b..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftlang.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftser2k.sys b/external/tellstick-driver/SerialDriver_Windows/amd64/ftser2k.sys deleted file mode 100644 index b8517be6..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftser2k.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/amd64/ftserui2.dll b/external/tellstick-driver/SerialDriver_Windows/amd64/ftserui2.dll deleted file mode 100644 index 0d116638..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/amd64/ftserui2.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/dpinst-amd64.exe b/external/tellstick-driver/SerialDriver_Windows/dpinst-amd64.exe deleted file mode 100644 index 055d2b49..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/dpinst-amd64.exe and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/dpinst-x86.exe b/external/tellstick-driver/SerialDriver_Windows/dpinst-x86.exe deleted file mode 100644 index 010c1b81..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/dpinst-x86.exe and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/ftd2xx.h b/external/tellstick-driver/SerialDriver_Windows/ftd2xx.h deleted file mode 100644 index 3c901d8e..00000000 --- a/external/tellstick-driver/SerialDriver_Windows/ftd2xx.h +++ /dev/null @@ -1,1341 +0,0 @@ -/*++ - -Copyright 2001-2011 Future Technology Devices International Limited - -THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. - -FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. - -IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE -RESPONSIBILITY OF THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL -RE-CERTIFICATION AS A RESULT OF MAKING THESE CHANGES. - - -Module Name: - -ftd2xx.h - -Abstract: - -Native USB device driver for FTDI FT232x, FT245x, FT2232x and FT4232x devices -FTD2XX library definitions - -Environment: - -kernel & user mode - - ---*/ - - -#ifndef FTD2XX_H -#define FTD2XX_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// FTD2XX_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef FTD2XX_EXPORTS -#define FTD2XX_API __declspec(dllexport) -#else -#define FTD2XX_API __declspec(dllimport) -#endif - - -typedef PVOID FT_HANDLE; -typedef ULONG FT_STATUS; - -// -// Device status -// -enum { - FT_OK, - FT_INVALID_HANDLE, - FT_DEVICE_NOT_FOUND, - FT_DEVICE_NOT_OPENED, - FT_IO_ERROR, - FT_INSUFFICIENT_RESOURCES, - FT_INVALID_PARAMETER, - FT_INVALID_BAUD_RATE, - - FT_DEVICE_NOT_OPENED_FOR_ERASE, - FT_DEVICE_NOT_OPENED_FOR_WRITE, - FT_FAILED_TO_WRITE_DEVICE, - FT_EEPROM_READ_FAILED, - FT_EEPROM_WRITE_FAILED, - FT_EEPROM_ERASE_FAILED, - FT_EEPROM_NOT_PRESENT, - FT_EEPROM_NOT_PROGRAMMED, - FT_INVALID_ARGS, - FT_NOT_SUPPORTED, - FT_OTHER_ERROR, - FT_DEVICE_LIST_NOT_READY, -}; - - -#define FT_SUCCESS(status) ((status) == FT_OK) - -// -// FT_OpenEx Flags -// - -#define FT_OPEN_BY_SERIAL_NUMBER 1 -#define FT_OPEN_BY_DESCRIPTION 2 -#define FT_OPEN_BY_LOCATION 4 - -// -// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags -// - -#define FT_LIST_NUMBER_ONLY 0x80000000 -#define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 - -#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) - -// -// Baud Rates -// - -#define FT_BAUD_300 300 -#define FT_BAUD_600 600 -#define FT_BAUD_1200 1200 -#define FT_BAUD_2400 2400 -#define FT_BAUD_4800 4800 -#define FT_BAUD_9600 9600 -#define FT_BAUD_14400 14400 -#define FT_BAUD_19200 19200 -#define FT_BAUD_38400 38400 -#define FT_BAUD_57600 57600 -#define FT_BAUD_115200 115200 -#define FT_BAUD_230400 230400 -#define FT_BAUD_460800 460800 -#define FT_BAUD_921600 921600 - -// -// Word Lengths -// - -#define FT_BITS_8 (UCHAR) 8 -#define FT_BITS_7 (UCHAR) 7 - -// -// Stop Bits -// - -#define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_2 (UCHAR) 2 - -// -// Parity -// - -#define FT_PARITY_NONE (UCHAR) 0 -#define FT_PARITY_ODD (UCHAR) 1 -#define FT_PARITY_EVEN (UCHAR) 2 -#define FT_PARITY_MARK (UCHAR) 3 -#define FT_PARITY_SPACE (UCHAR) 4 - -// -// Flow Control -// - -#define FT_FLOW_NONE 0x0000 -#define FT_FLOW_RTS_CTS 0x0100 -#define FT_FLOW_DTR_DSR 0x0200 -#define FT_FLOW_XON_XOFF 0x0400 - -// -// Purge rx and tx buffers -// -#define FT_PURGE_RX 1 -#define FT_PURGE_TX 2 - -// -// Events -// - -typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); - -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 -#define FT_EVENT_LINE_STATUS 4 - -// -// Timeouts -// - -#define FT_DEFAULT_RX_TIMEOUT 300 -#define FT_DEFAULT_TX_TIMEOUT 300 - -// -// Device types -// - -typedef ULONG FT_DEVICE; - -enum { - FT_DEVICE_BM, - FT_DEVICE_AM, - FT_DEVICE_100AX, - FT_DEVICE_UNKNOWN, - FT_DEVICE_2232C, - FT_DEVICE_232R, - FT_DEVICE_2232H, - FT_DEVICE_4232H, - FT_DEVICE_232H, - FT_DEVICE_X_SERIES -}; - -// -// Bit Modes -// - -#define FT_BITMODE_RESET 0x00 -#define FT_BITMODE_ASYNC_BITBANG 0x01 -#define FT_BITMODE_MPSSE 0x02 -#define FT_BITMODE_SYNC_BITBANG 0x04 -#define FT_BITMODE_MCU_HOST 0x08 -#define FT_BITMODE_FAST_SERIAL 0x10 -#define FT_BITMODE_CBUS_BITBANG 0x20 -#define FT_BITMODE_SYNC_FIFO 0x40 - -// -// FT232R CBUS Options EEPROM values -// - -#define FT_232R_CBUS_TXDEN 0x00 // Tx Data Enable -#define FT_232R_CBUS_PWRON 0x01 // Power On -#define FT_232R_CBUS_RXLED 0x02 // Rx LED -#define FT_232R_CBUS_TXLED 0x03 // Tx LED -#define FT_232R_CBUS_TXRXLED 0x04 // Tx and Rx LED -#define FT_232R_CBUS_SLEEP 0x05 // Sleep -#define FT_232R_CBUS_CLK48 0x06 // 48MHz clock -#define FT_232R_CBUS_CLK24 0x07 // 24MHz clock -#define FT_232R_CBUS_CLK12 0x08 // 12MHz clock -#define FT_232R_CBUS_CLK6 0x09 // 6MHz clock -#define FT_232R_CBUS_IOMODE 0x0A // IO Mode for CBUS bit-bang -#define FT_232R_CBUS_BITBANG_WR 0x0B // Bit-bang write strobe -#define FT_232R_CBUS_BITBANG_RD 0x0C // Bit-bang read strobe - -// -// FT232H CBUS Options EEPROM values -// - -#define FT_232H_CBUS_TRISTATE 0x00 // Tristate -#define FT_232H_CBUS_TXLED 0x01 // Tx LED -#define FT_232H_CBUS_RXLED 0x02 // Rx LED -#define FT_232H_CBUS_TXRXLED 0x03 // Tx and Rx LED -#define FT_232H_CBUS_PWREN 0x04 // Power Enable -#define FT_232H_CBUS_SLEEP 0x05 // Sleep -#define FT_232H_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 -#define FT_232H_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 -#define FT_232H_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang -#define FT_232H_CBUS_TXDEN 0x09 // Tx Data Enable -#define FT_232H_CBUS_CLK30 0x0A // 30MHz clock -#define FT_232H_CBUS_CLK15 0x0B // 15MHz clock -#define FT_232H_CBUS_CLK7_5 0x0C // 7.5MHz clock - -// -// FT X Series CBUS Options EEPROM values -// - -#define FT_X_SERIES_CBUS_TRISTATE 0x00 // Tristate -#define FT_X_SERIES_CBUS_RXLED 0x01 // Tx LED -#define FT_X_SERIES_CBUS_TXLED 0x02 // Rx LED -#define FT_X_SERIES_CBUS_TXRXLED 0x03 // Tx and Rx LED -#define FT_X_SERIES_CBUS_PWREN 0x04 // Power Enable -#define FT_X_SERIES_CBUS_SLEEP 0x05 // Sleep -#define FT_X_SERIES_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 -#define FT_X_SERIES_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 -#define FT_X_SERIES_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang -#define FT_X_SERIES_CBUS_TXDEN 0x09 // Tx Data Enable -#define FT_X_SERIES_CBUS_CLK24 0x0A // 24MHz clock -#define FT_X_SERIES_CBUS_CLK12 0x0B // 12MHz clock -#define FT_X_SERIES_CBUS_CLK6 0x0C // 6MHz clock -#define FT_X_SERIES_CBUS_BCD_CHARGER 0x0D // Battery charger detected -#define FT_X_SERIES_CBUS_BCD_CHARGER_N 0x0E // Battery charger detected inverted -#define FT_X_SERIES_CBUS_I2C_TXE 0x0F // I2C Tx empty -#define FT_X_SERIES_CBUS_I2C_RXF 0x10 // I2C Rx full -#define FT_X_SERIES_CBUS_VBUS_SENSE 0x11 // Detect VBUS -#define FT_X_SERIES_CBUS_BITBANG_WR 0x12 // Bit-bang write strobe -#define FT_X_SERIES_CBUS_BITBANG_RD 0x13 // Bit-bang read strobe -#define FT_X_SERIES_CBUS_TIMESTAMP 0x14 // Toggle output when a USB SOF token is received -#define FT_X_SERIES_CBUS_KEEP_AWAKE 0x15 // - - -// Driver types -#define FT_DRIVER_TYPE_D2XX 0 -#define FT_DRIVER_TYPE_VCP 1 - - - -#ifdef __cplusplus -extern "C" { -#endif - - - FTD2XX_API - FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToRead, - LPDWORD lpBytesReturned - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToWrite, - LPDWORD lpBytesWritten - ); - - FTD2XX_API - FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); - - // - // structure to hold program data for FT_EE_Program, FT_EE_ProgramEx, FT_EE_Read - // and FT_EE_ReadEx functions - // - typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232 extensions - // 2 = FT232R extensions - // 3 = FT2232H extensions - // 4 = FT4232H extensions - // 5 = FT232H extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 (FT232B) extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // Rev 5 (FT2232) extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // Rev 6 (FT232R) extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR RIsD2XX; // non-zero if using D2XX driver - // - // Rev 7 (FT2232H) Extensions - // - UCHAR PullDownEnable7; // non-zero if pull down enabled - UCHAR SerNumEnable7; // non-zero if serial number to be used - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial - UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial - UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // - // Rev 8 (FT4232H) Extensions - // - UCHAR PullDownEnable8; // non-zero if pull down enabled - UCHAR SerNumEnable8; // non-zero if serial number to be used - UCHAR ASlowSlew; // non-zero if A pins have slow slew - UCHAR ASchmittInput; // non-zero if A pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if B pins have slow slew - UCHAR BSchmittInput; // non-zero if B pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if C pins have slow slew - UCHAR CSchmittInput; // non-zero if C pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if D pins have slow slew - UCHAR DSchmittInput; // non-zero if D pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers - // - // Rev 9 (FT232H) Extensions - // - UCHAR PullDownEnableH; // non-zero if pull down enabled - UCHAR SerNumEnableH; // non-zero if serial number to be used - UCHAR ACSlowSlewH; // non-zero if AC pins have slow slew - UCHAR ACSchmittInputH; // non-zero if AC pins are Schmitt input - UCHAR ACDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlewH; // non-zero if AD pins have slow slew - UCHAR ADSchmittInputH; // non-zero if AD pins are Schmitt input - UCHAR ADDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR Cbus0H; // Cbus Mux control - UCHAR Cbus1H; // Cbus Mux control - UCHAR Cbus2H; // Cbus Mux control - UCHAR Cbus3H; // Cbus Mux control - UCHAR Cbus4H; // Cbus Mux control - UCHAR Cbus5H; // Cbus Mux control - UCHAR Cbus6H; // Cbus Mux control - UCHAR Cbus7H; // Cbus Mux control - UCHAR Cbus8H; // Cbus Mux control - UCHAR Cbus9H; // Cbus Mux control - UCHAR IsFifoH; // non-zero if interface is 245 FIFO - UCHAR IsFifoTarH; // non-zero if interface is 245 FIFO CPU target - UCHAR IsFastSerH; // non-zero if interface is Fast serial - UCHAR IsFT1248H; // non-zero if interface is FT1248 - UCHAR FT1248CpolH; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248LsbH; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControlH; // FT1248 flow control enable - UCHAR IsVCPH; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnableH; // non-zero if using ACBUS7 to save power for self-powered designs - - } FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - - FTD2XX_API - FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - - - typedef struct ft_eeprom_header { - FT_DEVICE deviceType; // FTxxxx device type to be programmed - // Device descriptor options - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - UCHAR SerNumEnable; // non-zero if serial number to be used - // Config descriptor options - WORD MaxPower; // 0 < MaxPower <= 500 - UCHAR SelfPowered; // 0 = bus powered, 1 = self powered - UCHAR RemoteWakeup; // 0 = not capable, 1 = capable - // Hardware options - UCHAR PullDownEnable; // non-zero if pull down in suspend enabled - } FT_EEPROM_HEADER, *PFT_EEPROM_HEADER; - - - // FT232B EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232b { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - } FT_EEPROM_232B, *PFT_EEPROM_232B; - - - // FT2232 EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_2232 { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - // Hardware options - UCHAR AIsFifo; // non-zero if interface is 245 FIFO - UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR AIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsFifo; // non-zero if interface is 245 FIFO - UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR BIsFastSer; // non-zero if interface is Fast serial - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - } FT_EEPROM_2232, *PFT_EEPROM_2232; - - - // FT232R EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232r { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR IsHighCurrent; // non-zero if interface is high current - // Hardware options - UCHAR UseExtOsc; // Use External Oscillator - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - // Driver option - UCHAR DriverType; // - } FT_EEPROM_232R, *PFT_EEPROM_232R; - - - // FT2232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_2232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // Hardware options - UCHAR AIsFifo; // non-zero if interface is 245 FIFO - UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR AIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsFifo; // non-zero if interface is 245 FIFO - UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR BIsFastSer; // non-zero if interface is Fast serial - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - } FT_EEPROM_2232H, *PFT_EEPROM_2232H; - - - // FT4232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_4232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ASlowSlew; // non-zero if A pins have slow slew - UCHAR ASchmittInput; // non-zero if A pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if B pins have slow slew - UCHAR BSchmittInput; // non-zero if B pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if C pins have slow slew - UCHAR CSchmittInput; // non-zero if C pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if D pins have slow slew - UCHAR DSchmittInput; // non-zero if D pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // Hardware options - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - UCHAR CDriverType; // - UCHAR DDriverType; // - } FT_EEPROM_4232H, *PFT_EEPROM_4232H; - - - // FT232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew - UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input - UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew - UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input - UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // CBUS options - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR Cbus5; // Cbus Mux control - UCHAR Cbus6; // Cbus Mux control - UCHAR Cbus7; // Cbus Mux control - UCHAR Cbus8; // Cbus Mux control - UCHAR Cbus9; // Cbus Mux control - // FT1248 options - UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControl; // FT1248 flow control enable - // Hardware options - UCHAR IsFifo; // non-zero if interface is 245 FIFO - UCHAR IsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IsFastSer; // non-zero if interface is Fast serial - UCHAR IsFT1248 ; // non-zero if interface is FT1248 - UCHAR PowerSaveEnable; // - // Driver option - UCHAR DriverType; // - } FT_EEPROM_232H, *PFT_EEPROM_232H; - - - // FT X Series EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_x_series { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew - UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input - UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew - UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input - UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // CBUS options - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR Cbus5; // Cbus Mux control - UCHAR Cbus6; // Cbus Mux control - // UART signal options - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - // Battery Charge Detect options - UCHAR BCDEnable; // Enable Battery Charger Detection - UCHAR BCDForceCbusPWREN; // asserts the power enable signal on CBUS when charging port detected - UCHAR BCDDisableSleep; // forces the device never to go into sleep mode - // I2C options - WORD I2CSlaveAddress; // I2C slave device address - DWORD I2CDeviceId; // I2C device ID - UCHAR I2CDisableSchmitt; // Disable I2C Schmitt trigger - // FT1248 options - UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControl; // FT1248 flow control enable - // Hardware options - UCHAR RS485EchoSuppress; // - UCHAR PowerSaveEnable; // - // Driver option - UCHAR DriverType; // - } FT_EEPROM_X_SERIES, *PFT_EEPROM_X_SERIES; - - - FTD2XX_API - FT_STATUS WINAPI FT_EEPROM_Read( - FT_HANDLE ftHandle, - void *eepromData, - DWORD eepromDataSize, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_EEPROM_Program( - FT_HANDLE ftHandle, - void *eepromData, - DWORD eepromDataSize, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDeadmanTimeout( - FT_HANDLE ftHandle, - ULONG ulDeadmanTimeout - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - - FTD2XX_API - FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_CyclePort( - FT_HANDLE ftHandle - ); - - - // - // Win32-type functions - // - - FTD2XX_API - FT_HANDLE WINAPI FT_W32_CreateFile( - LPCTSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - - FTD2XX_API - BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - - FTD2XX_API - BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); - - - // - // Win32 COMM API type functions - // - typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; - } FTCOMSTAT, *LPFTCOMSTAT; - - typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ - } FTDCB, *LPFTDCB; - - typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ - } FTTIMEOUTS,*LPFTTIMEOUTS; - - - FTD2XX_API - BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - - FTD2XX_API - BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - - FTD2XX_API - BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommMask( - FT_HANDLE ftHandle, - LPDWORD lpdwEventMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - - FTD2XX_API - BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); - - - // - // Device information - // - - typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; - } FT_DEVICE_LIST_INFO_NODE; - - // Device information flags - enum { - FT_FLAGS_OPENED = 1, - FT_FLAGS_HISPEED = 2 - }; - - - FTD2XX_API - FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); - - - // - // Version information - // - - FTD2XX_API - FT_STATUS WINAPI FT_GetDriverVersion( - FT_HANDLE ftHandle, - LPDWORD lpdwVersion - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetLibraryVersion( - LPDWORD lpdwVersion - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_Rescan( - void - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Reload( - WORD wVid, - WORD wPid - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetComPortNumber( - FT_HANDLE ftHandle, - LPLONG lpdwComPortNumber - ); - - - // - // FT232H additional EEPROM functions - // - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadConfig( - FT_HANDLE ftHandle, - UCHAR ucAddress, - PUCHAR pucValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_WriteConfig( - FT_HANDLE ftHandle, - UCHAR ucAddress, - UCHAR ucValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadECC( - FT_HANDLE ftHandle, - UCHAR ucOption, - LPWORD lpwValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetQueueStatusEx( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - - -#ifdef __cplusplus -} -#endif - - -#endif /* FTD2XX_H */ - diff --git a/external/tellstick-driver/SerialDriver_Windows/ftdibus.cat b/external/tellstick-driver/SerialDriver_Windows/ftdibus.cat deleted file mode 100644 index 5a1cd351..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/ftdibus.cat and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/ftdibus.inf b/external/tellstick-driver/SerialDriver_Windows/ftdibus.inf deleted file mode 100644 index e31f43a6..00000000 --- a/external/tellstick-driver/SerialDriver_Windows/ftdibus.inf +++ /dev/null @@ -1,159 +0,0 @@ -; FTDIBUS.INF -; -; Copyright � 2000-2013 Future Technology Devices International Limited -; -; USB serial converter driver installation file for Windows 2000, XP, Server 2003, Vista, Server 2008, -; Windows 7, Server 2008 R2 and Windows 8 (x86 and x64). -; -; -; THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED ``AS IS'' AND ANY EXPRESS -; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED -; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -; THE POSSIBILITY OF SUCH DAMAGE. - -; FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. - -; FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. - -; IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE RESPONSIBILITY OF -; THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL RE-CERTIFICATION AS A RESULT OF -; MAKING THESE CHANGES. -; - - -[Version] -Signature="$Windows NT$" -DriverPackageType=PlugAndPlay -DriverPackageDisplayName=%DESC% -Class=USB -ClassGUID={36fc9e60-c465-11cf-8056-444553540000} -Provider=%FTDI% -CatalogFile=ftdibus.cat -DriverVer=07/12/2013,2.08.30 - -[SourceDisksNames] -1=%DriversDisk%,,, - -[SourceDisksFiles] -ftdibus.sys = 1,i386 -ftbusui.dll = 1,i386 -ftd2xx.dll = 1,i386 -FTLang.Dll = 1,i386 - -[SourceDisksFiles.amd64] -ftdibus.sys = 1,amd64 -ftbusui.dll = 1,amd64 -ftd2xx64.dll = 1,amd64 -ftd2xx.dll = 1,i386 -FTLang.Dll = 1,amd64 - -[DestinationDirs] -FtdiBus.NT.Copy = 10,system32\drivers -FtdiBus.NT.Copy2 = 10,system32 -FtdiBus.NTamd64.Copy = 10,system32\drivers -FtdiBus.NTamd64.Copy2 = 10,system32 -FtdiBus.NTamd64.Copy3 = 10,syswow64 - - -[Manufacturer] -%Ftdi%=FtdiHw,NTamd64 - -[FtdiHw] -%USB\VID_0403&PID_6001.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6001 -%USB\VID_0403&PID_6010&MI_00.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6010&MI_00 -%USB\VID_0403&PID_6010&MI_01.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6010&MI_01 -%USB\VID_0403&PID_6011&MI_00.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_00 -%USB\VID_0403&PID_6011&MI_01.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_01 -%USB\VID_0403&PID_6011&MI_02.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_02 -%USB\VID_0403&PID_6011&MI_03.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_03 -%USB\VID_0403&PID_6014.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6014 -%USB\VID_0403&PID_6015.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6015 -%USB\VID_1781&PID_0C31.DeviceDesc%=FtdiBus.NT,USB\VID_1781&PID_0C31 - -[FtdiHw.NTamd64] -%USB\VID_0403&PID_6001.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6001 -%USB\VID_0403&PID_6010&MI_00.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6010&MI_00 -%USB\VID_0403&PID_6010&MI_01.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6010&MI_01 -%USB\VID_0403&PID_6011&MI_00.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_00 -%USB\VID_0403&PID_6011&MI_01.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_01 -%USB\VID_0403&PID_6011&MI_02.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_02 -%USB\VID_0403&PID_6011&MI_03.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_03 -%USB\VID_0403&PID_6014.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6014 -%USB\VID_0403&PID_6015.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6015 -%USB\VID_1781&PID_0C31.DeviceDesc%=FtdiBus.NTamd64,USB\VID_1781&PID_0C31 - -[ControlFlags] -ExcludeFromSelect=* - -[FtdiBus.NT] -CopyFiles=FtdiBus.NT.Copy,FtdiBus.NT.Copy2 -AddReg=FtdiBus.NT.AddReg - -[FtdiBus.NTamd64] -CopyFiles=FtdiBus.NTamd64.Copy,FtdiBus.NTamd64.Copy2,FtdiBus.NTamd64.Copy3 -AddReg=FtdiBus.NT.AddReg - -[FtdiBus.NT.Services] -AddService = FTDIBUS, 0x00000002, FtdiBus.NT.AddService - -[FtdiBus.NTamd64.Services] -AddService = FTDIBUS, 0x00000002, FtdiBus.NT.AddService - -[FtdiBus.NT.AddService] -DisplayName = %SvcDesc% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %10%\system32\drivers\ftdibus.sys -LoadOrderGroup = Base -AddReg = FtdiBus.NT.AddService.AddReg - -[FtdiBus.NT.AddReg] -HKR,,DevLoader,,*ntkern -HKR,,NTMPDriver,,ftdibus.sys -HKR,,EnumPropPages32,,"ftbusui.dll,FTBUSUIPropPageProvider" - -[FtdiBus.NT.AddService.AddReg] -;HKR,Parameters,"LocIds",1,31,00,00,00,32,00,00,00,00 -;HKR,Parameters,"RetryResetCount",0x10001,50 - - -[FtdiBus.NT.Copy] -ftdibus.sys - -[FtdiBus.NT.Copy2] -ftbusui.dll -ftd2xx.dll -FTLang.dll - -[FtdiBus.NTamd64.Copy] -ftdibus.sys - -[FtdiBus.NTamd64.Copy2] -ftbusui.dll -ftd2xx.dll,ftd2xx64.dll -FTLang.dll - -[FtdiBus.NTamd64.Copy3] -ftd2xx.dll - -[Strings] -Ftdi="FTDI" -DESC="CDM Driver Package - Bus/D2XX Driver" -DriversDisk="FTDI USB Drivers Disk" -USB\VID_0403&PID_6001.DeviceDesc="USB Serial Converter" -USB\VID_0403&PID_6010&MI_00.DeviceDesc="USB Serial Converter A" -USB\VID_0403&PID_6010&MI_01.DeviceDesc="USB Serial Converter B" -USB\VID_0403&PID_6011&MI_00.DeviceDesc="USB Serial Converter A" -USB\VID_0403&PID_6011&MI_01.DeviceDesc="USB Serial Converter B" -USB\VID_0403&PID_6011&MI_02.DeviceDesc="USB Serial Converter C" -USB\VID_0403&PID_6011&MI_03.DeviceDesc="USB Serial Converter D" -USB\VID_0403&PID_6014.DeviceDesc="USB Serial Converter" -USB\VID_0403&PID_6015.DeviceDesc="USB Serial Converter" -USB\VID_1781&PID_0C31.DeviceDesc="Tellstick Serial Converter" -SvcDesc="USB Serial Converter Driver" -ClassName="USB" diff --git a/external/tellstick-driver/SerialDriver_Windows/ftdiport.cat b/external/tellstick-driver/SerialDriver_Windows/ftdiport.cat deleted file mode 100644 index b052840b..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/ftdiport.cat and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/ftdiport.inf b/external/tellstick-driver/SerialDriver_Windows/ftdiport.inf deleted file mode 100644 index 158cdf7f..00000000 --- a/external/tellstick-driver/SerialDriver_Windows/ftdiport.inf +++ /dev/null @@ -1,170 +0,0 @@ -; FTDIPORT.INF -; -; Copyright � 2000-2013 Future Technology Devices International Limited -; -; USB serial port driver installation file for Windows 2000, XP, Server 2003, Vista, Server 2008, -; Windows 7, Server 2008 R2 and Windows 8 (x86 and x64). -; -; -; THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED ``AS IS'' AND ANY EXPRESS -; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED -; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -; THE POSSIBILITY OF SUCH DAMAGE. - -; FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. - -; FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. - -; IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE RESPONSIBILITY OF -; THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL RE-CERTIFICATION AS A RESULT OF -; MAKING THESE CHANGES. -; - - -[Version] -Signature="$Windows NT$" -DriverPackageType=PlugAndPlay -DriverPackageDisplayName=%DESC% -Class=Ports -ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318} -Provider=%FTDI% -CatalogFile=ftdiport.cat -DriverVer=07/12/2013,2.08.30 - -[SourceDisksNames] -1=%DriversDisk%,,, - -[SourceDisksFiles] -ftser2k.sys=1,i386 -ftserui2.dll=1,i386 -ftcserco.dll = 1,i386 - -[SourceDisksFiles.amd64] -ftser2k.sys=1,amd64 -ftserui2.dll=1,amd64 -ftcserco.dll = 1,amd64 - -[DestinationDirs] -FtdiPort.NT.Copy=10,system32\drivers -FtdiPort.NT.CopyUI=10,system32 -FtdiPort.NT.CopyCoInst=10,system32 - -[ControlFlags] -ExcludeFromSelect=* - -[Manufacturer] -%FTDI%=FtdiHw,NTamd64 - -[FtdiHw] -%VID_0403&PID_6001.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6001 -%VID_0403&PID_6010.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6010 -%VID_0403&PID_6011.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6011 -%VID_0403&PID_6014.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6014 -%VID_0403&PID_6015.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6015 -%VID_1781&PID_0C31.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_1781&PID_0C31 - -[FtdiHw.NTamd64] -%VID_0403&PID_6001.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6001 -%VID_0403&PID_6010.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6010 -%VID_0403&PID_6011.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6011 -%VID_0403&PID_6014.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6014 -%VID_0403&PID_6015.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6015 -%VID_1781&PID_0C31.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_1781&PID_0C31 - -[FtdiPort.NT.AddService] -DisplayName = %SvcDesc% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %10%\system32\drivers\ftser2k.sys -LoadOrderGroup = Base - - -; -------------- Serenum Driver install section -[SerEnum_AddService] -DisplayName = %SerEnum.SvcDesc% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %12%\serenum.sys -LoadOrderGroup = PNP Filter - -[FtdiPort.NT.AddReg] -HKR,,EnumPropPages32,,"ftserui2.dll,SerialPortPropPageProvider" - -[FtdiPort.NT.Copy] -ftser2k.sys - -[FtdiPort.NT.CopyUI] -ftserui2.dll - -[FtdiPort.NT.CopyCoInst] -ftcserco.dll - -[FtdiPort.NT] -CopyFiles=FtdiPort.NT.Copy,FtdiPort.NT.CopyUI -AddReg=FtdiPort.NT.AddReg - -[FtdiPort.NTamd64] -CopyFiles=FtdiPort.NT.Copy,FtdiPort.NT.CopyUI -AddReg=FtdiPort.NT.AddReg - -[FtdiPort.NT.HW] -AddReg=FtdiPort.NT.HW.AddReg - -[FtdiPort.NTamd64.HW] -AddReg=FtdiPort.NT.HW.AddReg - - -[FtdiPort.NT.Services] -AddService = FTSER2K, 0x00000002, FtdiPort.NT.AddService -AddService = Serenum,,SerEnum_AddService -DelService = FTSERIAL - -[FtdiPort.NTamd64.Services] -AddService = FTSER2K, 0x00000002, FtdiPort.NT.AddService -AddService = Serenum,,SerEnum_AddService -DelService = FTSERIAL - - -[FtdiPort.NT.HW.AddReg] -HKR,,"UpperFilters",0x00010000,"serenum" -HKR,,"ConfigData",1,11,00,3F,3F,10,27,00,00,88,13,00,00,C4,09,00,00,E2,04,00,00,71,02,00,00,38,41,00,00,9C,80,00,00,4E,C0,00,00,34,00,00,00,1A,00,00,00,0D,00,00,00,06,40,00,00,03,80,00,00,00,00,00,00,D0,80,00,00 -HKR,,"MinReadTimeout",0x00010001,0 -HKR,,"MinWriteTimeout",0x00010001,0 -HKR,,"LatencyTimer",0x00010001,16 - - -[FtdiPort.NT.CoInstallers] -AddReg=FtdiPort.NT.CoInstallers.AddReg -CopyFiles=FtdiPort.NT.CopyCoInst - -[FtdiPort.NTamd64.CoInstallers] -AddReg=FtdiPort.NT.CoInstallers.AddReg -CopyFiles=FtdiPort.NT.CopyCoInst - -[FtdiPort.NT.CoInstallers.AddReg] -HKR,,CoInstallers32,0x00010000,"ftcserco.Dll,FTCSERCoInstaller" - - -;---------------------------------------------------------------; - -[Strings] -FTDI="FTDI" -DESC="CDM Driver Package - VCP Driver" -DriversDisk="FTDI USB Drivers Disk" -PortsClassName = "Ports (COM & LPT)" -VID_0403&PID_6001.DeviceDesc="USB Serial Port" -VID_0403&PID_6010.DeviceDesc="USB Serial Port" -VID_0403&PID_6011.DeviceDesc="USB Serial Port" -VID_0403&PID_6014.DeviceDesc="USB Serial Port" -VID_0403&PID_6015.DeviceDesc="USB Serial Port" -VID_1781&PID_0C31.DeviceDesc="Tellstick Serial Port" -SvcDesc="USB Serial Port Driver" -SerEnum.SvcDesc="Serenum Filter Driver" - - diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftbusui.dll b/external/tellstick-driver/SerialDriver_Windows/i386/ftbusui.dll deleted file mode 100644 index 13bbf8f9..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftbusui.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftcserco.dll b/external/tellstick-driver/SerialDriver_Windows/i386/ftcserco.dll deleted file mode 100644 index dda7154d..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftcserco.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftd2xx.dll b/external/tellstick-driver/SerialDriver_Windows/i386/ftd2xx.dll deleted file mode 100644 index 859f821f..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftd2xx.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows/i386/ftd2xx.lib deleted file mode 100644 index 02eb5b58..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftdibus.sys b/external/tellstick-driver/SerialDriver_Windows/i386/ftdibus.sys deleted file mode 100644 index 8f0b0953..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftdibus.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftlang.dll b/external/tellstick-driver/SerialDriver_Windows/i386/ftlang.dll deleted file mode 100644 index 568382b0..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftlang.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftser2k.sys b/external/tellstick-driver/SerialDriver_Windows/i386/ftser2k.sys deleted file mode 100644 index 2f82ff7f..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftser2k.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/i386/ftserui2.dll b/external/tellstick-driver/SerialDriver_Windows/i386/ftserui2.dll deleted file mode 100644 index 5feacaa4..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/i386/ftserui2.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows/readme.txt b/external/tellstick-driver/SerialDriver_Windows/readme.txt deleted file mode 100644 index 20f74724..00000000 --- a/external/tellstick-driver/SerialDriver_Windows/readme.txt +++ /dev/null @@ -1 +0,0 @@ -This are the official FTDI Virtual Com Port divers (VCP-Drivers) version 2.08.30 where information about the product ID:s of Tellstick, FHZ1000 and FHZ1300 in the files ftdiport.inf and ftdibus.inf have been added. \ No newline at end of file diff --git a/external/tellstick-driver/SerialDriver_Windows/setup.exe b/external/tellstick-driver/SerialDriver_Windows/setup.exe deleted file mode 100644 index d79fdbe9..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows/setup.exe and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/Static/amd64/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows8_1/Static/amd64/ftd2xx.lib deleted file mode 100644 index 11509d69..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/Static/amd64/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/Static/i386/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows8_1/Static/i386/ftd2xx.lib deleted file mode 100644 index 3ff1d541..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/Static/i386/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftbusui.dll b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftbusui.dll deleted file mode 100644 index 398a1d82..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftbusui.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftcserco.dll b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftcserco.dll deleted file mode 100644 index 317d6a82..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftcserco.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftd2xx.lib deleted file mode 100644 index bb1669cd..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftd2xx64.dll b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftd2xx64.dll deleted file mode 100644 index 7ebc3b67..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftd2xx64.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftdibus.sys b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftdibus.sys deleted file mode 100644 index 208d6f14..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftdibus.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftlang.dll b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftlang.dll deleted file mode 100644 index 8b9ae95b..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftlang.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftser2k.sys b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftser2k.sys deleted file mode 100644 index b8517be6..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftser2k.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftserui2.dll b/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftserui2.dll deleted file mode 100644 index 0d116638..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/amd64/ftserui2.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/dpinst-amd64.exe b/external/tellstick-driver/SerialDriver_Windows8_1/dpinst-amd64.exe deleted file mode 100644 index 055d2b49..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/dpinst-amd64.exe and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/dpinst-x86.exe b/external/tellstick-driver/SerialDriver_Windows8_1/dpinst-x86.exe deleted file mode 100644 index 010c1b81..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/dpinst-x86.exe and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/ftd2xx.h b/external/tellstick-driver/SerialDriver_Windows8_1/ftd2xx.h deleted file mode 100644 index 3c901d8e..00000000 --- a/external/tellstick-driver/SerialDriver_Windows8_1/ftd2xx.h +++ /dev/null @@ -1,1341 +0,0 @@ -/*++ - -Copyright 2001-2011 Future Technology Devices International Limited - -THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. - -FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. - -IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE -RESPONSIBILITY OF THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL -RE-CERTIFICATION AS A RESULT OF MAKING THESE CHANGES. - - -Module Name: - -ftd2xx.h - -Abstract: - -Native USB device driver for FTDI FT232x, FT245x, FT2232x and FT4232x devices -FTD2XX library definitions - -Environment: - -kernel & user mode - - ---*/ - - -#ifndef FTD2XX_H -#define FTD2XX_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// FTD2XX_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef FTD2XX_EXPORTS -#define FTD2XX_API __declspec(dllexport) -#else -#define FTD2XX_API __declspec(dllimport) -#endif - - -typedef PVOID FT_HANDLE; -typedef ULONG FT_STATUS; - -// -// Device status -// -enum { - FT_OK, - FT_INVALID_HANDLE, - FT_DEVICE_NOT_FOUND, - FT_DEVICE_NOT_OPENED, - FT_IO_ERROR, - FT_INSUFFICIENT_RESOURCES, - FT_INVALID_PARAMETER, - FT_INVALID_BAUD_RATE, - - FT_DEVICE_NOT_OPENED_FOR_ERASE, - FT_DEVICE_NOT_OPENED_FOR_WRITE, - FT_FAILED_TO_WRITE_DEVICE, - FT_EEPROM_READ_FAILED, - FT_EEPROM_WRITE_FAILED, - FT_EEPROM_ERASE_FAILED, - FT_EEPROM_NOT_PRESENT, - FT_EEPROM_NOT_PROGRAMMED, - FT_INVALID_ARGS, - FT_NOT_SUPPORTED, - FT_OTHER_ERROR, - FT_DEVICE_LIST_NOT_READY, -}; - - -#define FT_SUCCESS(status) ((status) == FT_OK) - -// -// FT_OpenEx Flags -// - -#define FT_OPEN_BY_SERIAL_NUMBER 1 -#define FT_OPEN_BY_DESCRIPTION 2 -#define FT_OPEN_BY_LOCATION 4 - -// -// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags -// - -#define FT_LIST_NUMBER_ONLY 0x80000000 -#define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 - -#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) - -// -// Baud Rates -// - -#define FT_BAUD_300 300 -#define FT_BAUD_600 600 -#define FT_BAUD_1200 1200 -#define FT_BAUD_2400 2400 -#define FT_BAUD_4800 4800 -#define FT_BAUD_9600 9600 -#define FT_BAUD_14400 14400 -#define FT_BAUD_19200 19200 -#define FT_BAUD_38400 38400 -#define FT_BAUD_57600 57600 -#define FT_BAUD_115200 115200 -#define FT_BAUD_230400 230400 -#define FT_BAUD_460800 460800 -#define FT_BAUD_921600 921600 - -// -// Word Lengths -// - -#define FT_BITS_8 (UCHAR) 8 -#define FT_BITS_7 (UCHAR) 7 - -// -// Stop Bits -// - -#define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_2 (UCHAR) 2 - -// -// Parity -// - -#define FT_PARITY_NONE (UCHAR) 0 -#define FT_PARITY_ODD (UCHAR) 1 -#define FT_PARITY_EVEN (UCHAR) 2 -#define FT_PARITY_MARK (UCHAR) 3 -#define FT_PARITY_SPACE (UCHAR) 4 - -// -// Flow Control -// - -#define FT_FLOW_NONE 0x0000 -#define FT_FLOW_RTS_CTS 0x0100 -#define FT_FLOW_DTR_DSR 0x0200 -#define FT_FLOW_XON_XOFF 0x0400 - -// -// Purge rx and tx buffers -// -#define FT_PURGE_RX 1 -#define FT_PURGE_TX 2 - -// -// Events -// - -typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); - -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 -#define FT_EVENT_LINE_STATUS 4 - -// -// Timeouts -// - -#define FT_DEFAULT_RX_TIMEOUT 300 -#define FT_DEFAULT_TX_TIMEOUT 300 - -// -// Device types -// - -typedef ULONG FT_DEVICE; - -enum { - FT_DEVICE_BM, - FT_DEVICE_AM, - FT_DEVICE_100AX, - FT_DEVICE_UNKNOWN, - FT_DEVICE_2232C, - FT_DEVICE_232R, - FT_DEVICE_2232H, - FT_DEVICE_4232H, - FT_DEVICE_232H, - FT_DEVICE_X_SERIES -}; - -// -// Bit Modes -// - -#define FT_BITMODE_RESET 0x00 -#define FT_BITMODE_ASYNC_BITBANG 0x01 -#define FT_BITMODE_MPSSE 0x02 -#define FT_BITMODE_SYNC_BITBANG 0x04 -#define FT_BITMODE_MCU_HOST 0x08 -#define FT_BITMODE_FAST_SERIAL 0x10 -#define FT_BITMODE_CBUS_BITBANG 0x20 -#define FT_BITMODE_SYNC_FIFO 0x40 - -// -// FT232R CBUS Options EEPROM values -// - -#define FT_232R_CBUS_TXDEN 0x00 // Tx Data Enable -#define FT_232R_CBUS_PWRON 0x01 // Power On -#define FT_232R_CBUS_RXLED 0x02 // Rx LED -#define FT_232R_CBUS_TXLED 0x03 // Tx LED -#define FT_232R_CBUS_TXRXLED 0x04 // Tx and Rx LED -#define FT_232R_CBUS_SLEEP 0x05 // Sleep -#define FT_232R_CBUS_CLK48 0x06 // 48MHz clock -#define FT_232R_CBUS_CLK24 0x07 // 24MHz clock -#define FT_232R_CBUS_CLK12 0x08 // 12MHz clock -#define FT_232R_CBUS_CLK6 0x09 // 6MHz clock -#define FT_232R_CBUS_IOMODE 0x0A // IO Mode for CBUS bit-bang -#define FT_232R_CBUS_BITBANG_WR 0x0B // Bit-bang write strobe -#define FT_232R_CBUS_BITBANG_RD 0x0C // Bit-bang read strobe - -// -// FT232H CBUS Options EEPROM values -// - -#define FT_232H_CBUS_TRISTATE 0x00 // Tristate -#define FT_232H_CBUS_TXLED 0x01 // Tx LED -#define FT_232H_CBUS_RXLED 0x02 // Rx LED -#define FT_232H_CBUS_TXRXLED 0x03 // Tx and Rx LED -#define FT_232H_CBUS_PWREN 0x04 // Power Enable -#define FT_232H_CBUS_SLEEP 0x05 // Sleep -#define FT_232H_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 -#define FT_232H_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 -#define FT_232H_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang -#define FT_232H_CBUS_TXDEN 0x09 // Tx Data Enable -#define FT_232H_CBUS_CLK30 0x0A // 30MHz clock -#define FT_232H_CBUS_CLK15 0x0B // 15MHz clock -#define FT_232H_CBUS_CLK7_5 0x0C // 7.5MHz clock - -// -// FT X Series CBUS Options EEPROM values -// - -#define FT_X_SERIES_CBUS_TRISTATE 0x00 // Tristate -#define FT_X_SERIES_CBUS_RXLED 0x01 // Tx LED -#define FT_X_SERIES_CBUS_TXLED 0x02 // Rx LED -#define FT_X_SERIES_CBUS_TXRXLED 0x03 // Tx and Rx LED -#define FT_X_SERIES_CBUS_PWREN 0x04 // Power Enable -#define FT_X_SERIES_CBUS_SLEEP 0x05 // Sleep -#define FT_X_SERIES_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 -#define FT_X_SERIES_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 -#define FT_X_SERIES_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang -#define FT_X_SERIES_CBUS_TXDEN 0x09 // Tx Data Enable -#define FT_X_SERIES_CBUS_CLK24 0x0A // 24MHz clock -#define FT_X_SERIES_CBUS_CLK12 0x0B // 12MHz clock -#define FT_X_SERIES_CBUS_CLK6 0x0C // 6MHz clock -#define FT_X_SERIES_CBUS_BCD_CHARGER 0x0D // Battery charger detected -#define FT_X_SERIES_CBUS_BCD_CHARGER_N 0x0E // Battery charger detected inverted -#define FT_X_SERIES_CBUS_I2C_TXE 0x0F // I2C Tx empty -#define FT_X_SERIES_CBUS_I2C_RXF 0x10 // I2C Rx full -#define FT_X_SERIES_CBUS_VBUS_SENSE 0x11 // Detect VBUS -#define FT_X_SERIES_CBUS_BITBANG_WR 0x12 // Bit-bang write strobe -#define FT_X_SERIES_CBUS_BITBANG_RD 0x13 // Bit-bang read strobe -#define FT_X_SERIES_CBUS_TIMESTAMP 0x14 // Toggle output when a USB SOF token is received -#define FT_X_SERIES_CBUS_KEEP_AWAKE 0x15 // - - -// Driver types -#define FT_DRIVER_TYPE_D2XX 0 -#define FT_DRIVER_TYPE_VCP 1 - - - -#ifdef __cplusplus -extern "C" { -#endif - - - FTD2XX_API - FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToRead, - LPDWORD lpBytesReturned - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToWrite, - LPDWORD lpBytesWritten - ); - - FTD2XX_API - FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); - - // - // structure to hold program data for FT_EE_Program, FT_EE_ProgramEx, FT_EE_Read - // and FT_EE_ReadEx functions - // - typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232 extensions - // 2 = FT232R extensions - // 3 = FT2232H extensions - // 4 = FT4232H extensions - // 5 = FT232H extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 (FT232B) extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // Rev 5 (FT2232) extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // Rev 6 (FT232R) extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR RIsD2XX; // non-zero if using D2XX driver - // - // Rev 7 (FT2232H) Extensions - // - UCHAR PullDownEnable7; // non-zero if pull down enabled - UCHAR SerNumEnable7; // non-zero if serial number to be used - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial - UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial - UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // - // Rev 8 (FT4232H) Extensions - // - UCHAR PullDownEnable8; // non-zero if pull down enabled - UCHAR SerNumEnable8; // non-zero if serial number to be used - UCHAR ASlowSlew; // non-zero if A pins have slow slew - UCHAR ASchmittInput; // non-zero if A pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if B pins have slow slew - UCHAR BSchmittInput; // non-zero if B pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if C pins have slow slew - UCHAR CSchmittInput; // non-zero if C pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if D pins have slow slew - UCHAR DSchmittInput; // non-zero if D pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers - // - // Rev 9 (FT232H) Extensions - // - UCHAR PullDownEnableH; // non-zero if pull down enabled - UCHAR SerNumEnableH; // non-zero if serial number to be used - UCHAR ACSlowSlewH; // non-zero if AC pins have slow slew - UCHAR ACSchmittInputH; // non-zero if AC pins are Schmitt input - UCHAR ACDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlewH; // non-zero if AD pins have slow slew - UCHAR ADSchmittInputH; // non-zero if AD pins are Schmitt input - UCHAR ADDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR Cbus0H; // Cbus Mux control - UCHAR Cbus1H; // Cbus Mux control - UCHAR Cbus2H; // Cbus Mux control - UCHAR Cbus3H; // Cbus Mux control - UCHAR Cbus4H; // Cbus Mux control - UCHAR Cbus5H; // Cbus Mux control - UCHAR Cbus6H; // Cbus Mux control - UCHAR Cbus7H; // Cbus Mux control - UCHAR Cbus8H; // Cbus Mux control - UCHAR Cbus9H; // Cbus Mux control - UCHAR IsFifoH; // non-zero if interface is 245 FIFO - UCHAR IsFifoTarH; // non-zero if interface is 245 FIFO CPU target - UCHAR IsFastSerH; // non-zero if interface is Fast serial - UCHAR IsFT1248H; // non-zero if interface is FT1248 - UCHAR FT1248CpolH; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248LsbH; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControlH; // FT1248 flow control enable - UCHAR IsVCPH; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnableH; // non-zero if using ACBUS7 to save power for self-powered designs - - } FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - - FTD2XX_API - FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - - - typedef struct ft_eeprom_header { - FT_DEVICE deviceType; // FTxxxx device type to be programmed - // Device descriptor options - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - UCHAR SerNumEnable; // non-zero if serial number to be used - // Config descriptor options - WORD MaxPower; // 0 < MaxPower <= 500 - UCHAR SelfPowered; // 0 = bus powered, 1 = self powered - UCHAR RemoteWakeup; // 0 = not capable, 1 = capable - // Hardware options - UCHAR PullDownEnable; // non-zero if pull down in suspend enabled - } FT_EEPROM_HEADER, *PFT_EEPROM_HEADER; - - - // FT232B EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232b { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - } FT_EEPROM_232B, *PFT_EEPROM_232B; - - - // FT2232 EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_2232 { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - // Hardware options - UCHAR AIsFifo; // non-zero if interface is 245 FIFO - UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR AIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsFifo; // non-zero if interface is 245 FIFO - UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR BIsFastSer; // non-zero if interface is Fast serial - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - } FT_EEPROM_2232, *PFT_EEPROM_2232; - - - // FT232R EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232r { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR IsHighCurrent; // non-zero if interface is high current - // Hardware options - UCHAR UseExtOsc; // Use External Oscillator - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - // Driver option - UCHAR DriverType; // - } FT_EEPROM_232R, *PFT_EEPROM_232R; - - - // FT2232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_2232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // Hardware options - UCHAR AIsFifo; // non-zero if interface is 245 FIFO - UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR AIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsFifo; // non-zero if interface is 245 FIFO - UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR BIsFastSer; // non-zero if interface is Fast serial - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - } FT_EEPROM_2232H, *PFT_EEPROM_2232H; - - - // FT4232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_4232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ASlowSlew; // non-zero if A pins have slow slew - UCHAR ASchmittInput; // non-zero if A pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if B pins have slow slew - UCHAR BSchmittInput; // non-zero if B pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if C pins have slow slew - UCHAR CSchmittInput; // non-zero if C pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if D pins have slow slew - UCHAR DSchmittInput; // non-zero if D pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // Hardware options - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - UCHAR CDriverType; // - UCHAR DDriverType; // - } FT_EEPROM_4232H, *PFT_EEPROM_4232H; - - - // FT232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew - UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input - UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew - UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input - UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // CBUS options - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR Cbus5; // Cbus Mux control - UCHAR Cbus6; // Cbus Mux control - UCHAR Cbus7; // Cbus Mux control - UCHAR Cbus8; // Cbus Mux control - UCHAR Cbus9; // Cbus Mux control - // FT1248 options - UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControl; // FT1248 flow control enable - // Hardware options - UCHAR IsFifo; // non-zero if interface is 245 FIFO - UCHAR IsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IsFastSer; // non-zero if interface is Fast serial - UCHAR IsFT1248 ; // non-zero if interface is FT1248 - UCHAR PowerSaveEnable; // - // Driver option - UCHAR DriverType; // - } FT_EEPROM_232H, *PFT_EEPROM_232H; - - - // FT X Series EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_x_series { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew - UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input - UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew - UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input - UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // CBUS options - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR Cbus5; // Cbus Mux control - UCHAR Cbus6; // Cbus Mux control - // UART signal options - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - // Battery Charge Detect options - UCHAR BCDEnable; // Enable Battery Charger Detection - UCHAR BCDForceCbusPWREN; // asserts the power enable signal on CBUS when charging port detected - UCHAR BCDDisableSleep; // forces the device never to go into sleep mode - // I2C options - WORD I2CSlaveAddress; // I2C slave device address - DWORD I2CDeviceId; // I2C device ID - UCHAR I2CDisableSchmitt; // Disable I2C Schmitt trigger - // FT1248 options - UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControl; // FT1248 flow control enable - // Hardware options - UCHAR RS485EchoSuppress; // - UCHAR PowerSaveEnable; // - // Driver option - UCHAR DriverType; // - } FT_EEPROM_X_SERIES, *PFT_EEPROM_X_SERIES; - - - FTD2XX_API - FT_STATUS WINAPI FT_EEPROM_Read( - FT_HANDLE ftHandle, - void *eepromData, - DWORD eepromDataSize, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_EEPROM_Program( - FT_HANDLE ftHandle, - void *eepromData, - DWORD eepromDataSize, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDeadmanTimeout( - FT_HANDLE ftHandle, - ULONG ulDeadmanTimeout - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - - FTD2XX_API - FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_CyclePort( - FT_HANDLE ftHandle - ); - - - // - // Win32-type functions - // - - FTD2XX_API - FT_HANDLE WINAPI FT_W32_CreateFile( - LPCTSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - - FTD2XX_API - BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - - FTD2XX_API - BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); - - - // - // Win32 COMM API type functions - // - typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; - } FTCOMSTAT, *LPFTCOMSTAT; - - typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ - } FTDCB, *LPFTDCB; - - typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ - } FTTIMEOUTS,*LPFTTIMEOUTS; - - - FTD2XX_API - BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - - FTD2XX_API - BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - - FTD2XX_API - BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommMask( - FT_HANDLE ftHandle, - LPDWORD lpdwEventMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - - FTD2XX_API - BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); - - - // - // Device information - // - - typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; - } FT_DEVICE_LIST_INFO_NODE; - - // Device information flags - enum { - FT_FLAGS_OPENED = 1, - FT_FLAGS_HISPEED = 2 - }; - - - FTD2XX_API - FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); - - - // - // Version information - // - - FTD2XX_API - FT_STATUS WINAPI FT_GetDriverVersion( - FT_HANDLE ftHandle, - LPDWORD lpdwVersion - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetLibraryVersion( - LPDWORD lpdwVersion - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_Rescan( - void - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Reload( - WORD wVid, - WORD wPid - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetComPortNumber( - FT_HANDLE ftHandle, - LPLONG lpdwComPortNumber - ); - - - // - // FT232H additional EEPROM functions - // - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadConfig( - FT_HANDLE ftHandle, - UCHAR ucAddress, - PUCHAR pucValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_WriteConfig( - FT_HANDLE ftHandle, - UCHAR ucAddress, - UCHAR ucValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadECC( - FT_HANDLE ftHandle, - UCHAR ucOption, - LPWORD lpwValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetQueueStatusEx( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - - -#ifdef __cplusplus -} -#endif - - -#endif /* FTD2XX_H */ - diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/ftdibus.cat b/external/tellstick-driver/SerialDriver_Windows8_1/ftdibus.cat deleted file mode 100644 index 5c5796b1..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/ftdibus.cat and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/ftdibus.inf b/external/tellstick-driver/SerialDriver_Windows8_1/ftdibus.inf deleted file mode 100644 index e31f43a6..00000000 --- a/external/tellstick-driver/SerialDriver_Windows8_1/ftdibus.inf +++ /dev/null @@ -1,159 +0,0 @@ -; FTDIBUS.INF -; -; Copyright � 2000-2013 Future Technology Devices International Limited -; -; USB serial converter driver installation file for Windows 2000, XP, Server 2003, Vista, Server 2008, -; Windows 7, Server 2008 R2 and Windows 8 (x86 and x64). -; -; -; THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED ``AS IS'' AND ANY EXPRESS -; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED -; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -; THE POSSIBILITY OF SUCH DAMAGE. - -; FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. - -; FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. - -; IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE RESPONSIBILITY OF -; THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL RE-CERTIFICATION AS A RESULT OF -; MAKING THESE CHANGES. -; - - -[Version] -Signature="$Windows NT$" -DriverPackageType=PlugAndPlay -DriverPackageDisplayName=%DESC% -Class=USB -ClassGUID={36fc9e60-c465-11cf-8056-444553540000} -Provider=%FTDI% -CatalogFile=ftdibus.cat -DriverVer=07/12/2013,2.08.30 - -[SourceDisksNames] -1=%DriversDisk%,,, - -[SourceDisksFiles] -ftdibus.sys = 1,i386 -ftbusui.dll = 1,i386 -ftd2xx.dll = 1,i386 -FTLang.Dll = 1,i386 - -[SourceDisksFiles.amd64] -ftdibus.sys = 1,amd64 -ftbusui.dll = 1,amd64 -ftd2xx64.dll = 1,amd64 -ftd2xx.dll = 1,i386 -FTLang.Dll = 1,amd64 - -[DestinationDirs] -FtdiBus.NT.Copy = 10,system32\drivers -FtdiBus.NT.Copy2 = 10,system32 -FtdiBus.NTamd64.Copy = 10,system32\drivers -FtdiBus.NTamd64.Copy2 = 10,system32 -FtdiBus.NTamd64.Copy3 = 10,syswow64 - - -[Manufacturer] -%Ftdi%=FtdiHw,NTamd64 - -[FtdiHw] -%USB\VID_0403&PID_6001.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6001 -%USB\VID_0403&PID_6010&MI_00.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6010&MI_00 -%USB\VID_0403&PID_6010&MI_01.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6010&MI_01 -%USB\VID_0403&PID_6011&MI_00.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_00 -%USB\VID_0403&PID_6011&MI_01.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_01 -%USB\VID_0403&PID_6011&MI_02.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_02 -%USB\VID_0403&PID_6011&MI_03.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6011&MI_03 -%USB\VID_0403&PID_6014.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6014 -%USB\VID_0403&PID_6015.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6015 -%USB\VID_1781&PID_0C31.DeviceDesc%=FtdiBus.NT,USB\VID_1781&PID_0C31 - -[FtdiHw.NTamd64] -%USB\VID_0403&PID_6001.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6001 -%USB\VID_0403&PID_6010&MI_00.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6010&MI_00 -%USB\VID_0403&PID_6010&MI_01.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6010&MI_01 -%USB\VID_0403&PID_6011&MI_00.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_00 -%USB\VID_0403&PID_6011&MI_01.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_01 -%USB\VID_0403&PID_6011&MI_02.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_02 -%USB\VID_0403&PID_6011&MI_03.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6011&MI_03 -%USB\VID_0403&PID_6014.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6014 -%USB\VID_0403&PID_6015.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6015 -%USB\VID_1781&PID_0C31.DeviceDesc%=FtdiBus.NTamd64,USB\VID_1781&PID_0C31 - -[ControlFlags] -ExcludeFromSelect=* - -[FtdiBus.NT] -CopyFiles=FtdiBus.NT.Copy,FtdiBus.NT.Copy2 -AddReg=FtdiBus.NT.AddReg - -[FtdiBus.NTamd64] -CopyFiles=FtdiBus.NTamd64.Copy,FtdiBus.NTamd64.Copy2,FtdiBus.NTamd64.Copy3 -AddReg=FtdiBus.NT.AddReg - -[FtdiBus.NT.Services] -AddService = FTDIBUS, 0x00000002, FtdiBus.NT.AddService - -[FtdiBus.NTamd64.Services] -AddService = FTDIBUS, 0x00000002, FtdiBus.NT.AddService - -[FtdiBus.NT.AddService] -DisplayName = %SvcDesc% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %10%\system32\drivers\ftdibus.sys -LoadOrderGroup = Base -AddReg = FtdiBus.NT.AddService.AddReg - -[FtdiBus.NT.AddReg] -HKR,,DevLoader,,*ntkern -HKR,,NTMPDriver,,ftdibus.sys -HKR,,EnumPropPages32,,"ftbusui.dll,FTBUSUIPropPageProvider" - -[FtdiBus.NT.AddService.AddReg] -;HKR,Parameters,"LocIds",1,31,00,00,00,32,00,00,00,00 -;HKR,Parameters,"RetryResetCount",0x10001,50 - - -[FtdiBus.NT.Copy] -ftdibus.sys - -[FtdiBus.NT.Copy2] -ftbusui.dll -ftd2xx.dll -FTLang.dll - -[FtdiBus.NTamd64.Copy] -ftdibus.sys - -[FtdiBus.NTamd64.Copy2] -ftbusui.dll -ftd2xx.dll,ftd2xx64.dll -FTLang.dll - -[FtdiBus.NTamd64.Copy3] -ftd2xx.dll - -[Strings] -Ftdi="FTDI" -DESC="CDM Driver Package - Bus/D2XX Driver" -DriversDisk="FTDI USB Drivers Disk" -USB\VID_0403&PID_6001.DeviceDesc="USB Serial Converter" -USB\VID_0403&PID_6010&MI_00.DeviceDesc="USB Serial Converter A" -USB\VID_0403&PID_6010&MI_01.DeviceDesc="USB Serial Converter B" -USB\VID_0403&PID_6011&MI_00.DeviceDesc="USB Serial Converter A" -USB\VID_0403&PID_6011&MI_01.DeviceDesc="USB Serial Converter B" -USB\VID_0403&PID_6011&MI_02.DeviceDesc="USB Serial Converter C" -USB\VID_0403&PID_6011&MI_03.DeviceDesc="USB Serial Converter D" -USB\VID_0403&PID_6014.DeviceDesc="USB Serial Converter" -USB\VID_0403&PID_6015.DeviceDesc="USB Serial Converter" -USB\VID_1781&PID_0C31.DeviceDesc="Tellstick Serial Converter" -SvcDesc="USB Serial Converter Driver" -ClassName="USB" diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/ftdiport.cat b/external/tellstick-driver/SerialDriver_Windows8_1/ftdiport.cat deleted file mode 100644 index 4cf2b5b6..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/ftdiport.cat and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/ftdiport.inf b/external/tellstick-driver/SerialDriver_Windows8_1/ftdiport.inf deleted file mode 100644 index ba958ca5..00000000 --- a/external/tellstick-driver/SerialDriver_Windows8_1/ftdiport.inf +++ /dev/null @@ -1,170 +0,0 @@ -; FTDIPORT.INF -; -; Copyright � 2000-2013 Future Technology Devices International Limited -; -; USB serial port driver installation file for Windows 2000, XP, Server 2003, Vista, Server 2008, -; Windows 7, Server 2008 R2 and Windows 8 (x86 and x64). -; -; -; THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED ``AS IS'' AND ANY EXPRESS -; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED -; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -; THE POSSIBILITY OF SUCH DAMAGE. - -; FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. - -; FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. - -; IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE RESPONSIBILITY OF -; THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL RE-CERTIFICATION AS A RESULT OF -; MAKING THESE CHANGES. -; - - -[Version] -Signature="$Windows NT$" -DriverPackageType=PlugAndPlay -DriverPackageDisplayName=%DESC% -Class=Ports -ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318} -Provider=%FTDI% -CatalogFile=ftdiport.cat -DriverVer=07/12/2013,2.08.30 - -[SourceDisksNames] -1=%DriversDisk%,,, - -[SourceDisksFiles] -ftser2k.sys=1,i386 -ftserui2.dll=1,i386 -ftcserco.dll = 1,i386 - -[SourceDisksFiles.amd64] -ftser2k.sys=1,amd64 -ftserui2.dll=1,amd64 -ftcserco.dll = 1,amd64 - -[DestinationDirs] -FtdiPort.NT.Copy=10,system32\drivers -FtdiPort.NT.CopyUI=10,system32 -FtdiPort.NT.CopyCoInst=10,system32 - -[ControlFlags] -ExcludeFromSelect=* - -[Manufacturer] -%FTDI%=FtdiHw,NTamd64 - -[FtdiHw] -%VID_0403&PID_6001.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6001 -%VID_0403&PID_6010.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6010 -%VID_0403&PID_6011.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6011 -%VID_0403&PID_6014.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6014 -%VID_0403&PID_6015.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_0403&PID_6015 -%VID_1781&PID_0C31.DeviceDesc%=FtdiPort.NT,FTDIBUS\COMPORT&VID_1781&PID_0C31 - -[FtdiHw.NTamd64] -%VID_0403&PID_6001.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6001 -%VID_0403&PID_6010.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6010 -%VID_0403&PID_6011.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6011 -%VID_0403&PID_6014.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6014 -%VID_0403&PID_6015.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6015 -%VID_1781&PID_0C31.DeviceDesc%=FtdiPort.NTamd64,FTDIBUS\COMPORT&VID_1781&PID_0C31 - -[FtdiPort.NT.AddService] -DisplayName = %SvcDesc% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %10%\system32\drivers\ftser2k.sys -LoadOrderGroup = Base - - -; -------------- Serenum Driver install section -[SerEnum_AddService] -DisplayName = %SerEnum.SvcDesc% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %12%\serenum.sys -LoadOrderGroup = PNP Filter - -[FtdiPort.NT.AddReg] -HKR,,EnumPropPages32,,"ftserui2.dll,SerialPortPropPageProvider" - -[FtdiPort.NT.Copy] -ftser2k.sys - -[FtdiPort.NT.CopyUI] -ftserui2.dll - -[FtdiPort.NT.CopyCoInst] -ftcserco.dll - -[FtdiPort.NT] -CopyFiles=FtdiPort.NT.Copy,FtdiPort.NT.CopyUI -AddReg=FtdiPort.NT.AddReg - -[FtdiPort.NTamd64] -CopyFiles=FtdiPort.NT.Copy,FtdiPort.NT.CopyUI -AddReg=FtdiPort.NT.AddReg - -[FtdiPort.NT.HW] -AddReg=FtdiPort.NT.HW.AddReg - -[FtdiPort.NTamd64.HW] -AddReg=FtdiPort.NT.HW.AddReg - - -[FtdiPort.NT.Services] -AddService = FTSER2K, 0x00000002, FtdiPort.NT.AddService -AddService = Serenum,,SerEnum_AddService -DelService = FTSERIAL - -[FtdiPort.NTamd64.Services] -AddService = FTSER2K, 0x00000002, FtdiPort.NT.AddService -AddService = Serenum,,SerEnum_AddService -DelService = FTSERIAL - - -[FtdiPort.NT.HW.AddReg] -HKR,,"UpperFilters",0x00010000,"serenum" -HKR,,"ConfigData",1,11,00,3F,3F,10,27,00,00,88,13,00,00,C4,09,00,00,E2,04,00,00,71,02,00,00,38,41,00,00,9C,80,00,00,4E,C0,00,00,34,00,00,00,1A,00,00,00,0D,00,00,00,06,40,00,00,03,80,00,00,00,00,00,00,D0,80,00,00 -HKR,,"MinReadTimeout",0x00010001,0 -HKR,,"MinWriteTimeout",0x00010001,0 -HKR,,"LatencyTimer",0x00010001,16 - - -[FtdiPort.NT.CoInstallers] -AddReg=FtdiPort.NT.CoInstallers.AddReg -CopyFiles=FtdiPort.NT.CopyCoInst - -[FtdiPort.NTamd64.CoInstallers] -AddReg=FtdiPort.NT.CoInstallers.AddReg -CopyFiles=FtdiPort.NT.CopyCoInst - -[FtdiPort.NT.CoInstallers.AddReg] -HKR,,CoInstallers32,0x00010000,"ftcserco.Dll,FTCSERCoInstaller" - - -;---------------------------------------------------------------; - -[Strings] -FTDI="FTDI" -DESC="CDM Driver Package - VCP Driver" -DriversDisk="FTDI USB Drivers Disk" -PortsClassName = "Ports (COM & LPT)" -VID_0403&PID_6001.DeviceDesc="USB Serial Port" -VID_0403&PID_6010.DeviceDesc="USB Serial Port" -VID_0403&PID_6011.DeviceDesc="USB Serial Port" -VID_0403&PID_6014.DeviceDesc="USB Serial Port" -VID_0403&PID_6015.DeviceDesc="USB Serial Port" -VID_1781&PID_0C31.DeviceDesc="Tellstick Serial Port" -SvcDesc="USB Serial Port Driver" -SerEnum.SvcDesc="Serenum Filter Driver" - - diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftbusui.dll b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftbusui.dll deleted file mode 100644 index 13bbf8f9..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftbusui.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftcserco.dll b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftcserco.dll deleted file mode 100644 index dda7154d..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftcserco.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftd2xx.dll b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftd2xx.dll deleted file mode 100644 index 859f821f..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftd2xx.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftd2xx.lib b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftd2xx.lib deleted file mode 100644 index 02eb5b58..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftd2xx.lib and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftdibus.sys b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftdibus.sys deleted file mode 100644 index 8f0b0953..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftdibus.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftlang.dll b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftlang.dll deleted file mode 100644 index 568382b0..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftlang.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftser2k.sys b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftser2k.sys deleted file mode 100644 index 2f82ff7f..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftser2k.sys and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftserui2.dll b/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftserui2.dll deleted file mode 100644 index 5feacaa4..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/i386/ftserui2.dll and /dev/null differ diff --git a/external/tellstick-driver/SerialDriver_Windows8_1/setup.exe b/external/tellstick-driver/SerialDriver_Windows8_1/setup.exe deleted file mode 100644 index d79fdbe9..00000000 Binary files a/external/tellstick-driver/SerialDriver_Windows8_1/setup.exe and /dev/null differ diff --git a/external/tellstick-driver/ftdi_linux.zip b/external/tellstick-driver/ftdi_linux.zip deleted file mode 100644 index 29243481..00000000 Binary files a/external/tellstick-driver/ftdi_linux.zip and /dev/null differ diff --git a/external/tellstick-rfcmd/CMakeLists.txt b/external/tellstick-rfcmd/CMakeLists.txt deleted file mode 100644 index af4b4484..00000000 --- a/external/tellstick-rfcmd/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -cmake_minimum_required(VERSION 2.4) - -INCLUDE_DIRECTORIES( - /usr/src/linux/include -) - -#### Project: rfcmd #### - -PROJECT(rfcmd) - -SET(rfcmd_DESCRIPTION - "Sends RF remote commands through a Telldus TellStick" -) - -SET(rfcmd_SRCS - rfcmd.c -) - -IF(${RFCMD_DEBUG}) - ADD_DEFINITIONS( -DRFCMD_DEBUG ) -ENDIF(${RFCMD_DEBUG}) - -IF (BUILD_RFCMD_WITH_LIBFTDI) - ADD_DEFINITIONS( -DLIBFTDI ) - - SET(rfcmd_SRCS - ${rfcmd_SRCS} - ftdi.c - ) -ENDIF (BUILD_RFCMD_WITH_LIBFTDI) -ADD_EXECUTABLE(rfcmd - ${rfcmd_SRCS} -) - -IF (BUILD_RFCMD_WITH_SEMAPHORES) - FIND_LIBRARY(SEM_LIBRARY rt) - TARGET_LINK_LIBRARIES(rfcmd - ${SEM_LIBRARY} - ) -ELSE (BUILD_RFCMD_WITH_SEMAPHORES) - ADD_DEFINITIONS( -DNO_SEMAPHORES ) -ENDIF (BUILD_RFCMD_WITH_SEMAPHORES) - - - -IF (BUILD_RFCMD_WITH_LIBFTDI) - FIND_LIBRARY(FTDI_LIBRARY ftdi) - - TARGET_LINK_LIBRARIES(rfcmd - ${FTDI_LIBRARY} - ) -ENDIF (BUILD_RFCMD_WITH_LIBFTDI) - -INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) - -IF (UNIX) - IF (GENERATE_MAN) - ADD_CUSTOM_COMMAND( - TARGET rfcmd - POST_BUILD - COMMAND help2man -n ${rfcmd_DESCRIPTION} ./rfcmd > rfcmd.1 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating man file rfcmd.1" - ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/rfcmd.1 DESTINATION share/man/man1) - ENDIF (GENERATE_MAN) -ENDIF (UNIX) - -#### Project: find_telldus #### - -IF (BUILD_RFCMD_WITH_LIBFTDI) - PROJECT(find_telldus) - - SET(find_telldus_SRCS - find_telldus.c - ) - - ADD_EXECUTABLE(find_telldus - ${find_telldus_SRCS} - ) - - TARGET_LINK_LIBRARIES(find_telldus - ${FTDI_LIBRARY} - ) - - INSTALL(TARGETS find_telldus RUNTIME DESTINATION bin) - -ENDIF (BUILD_RFCMD_WITH_LIBFTDI) diff --git a/external/tellstick-rfcmd/COPYING b/external/tellstick-rfcmd/COPYING deleted file mode 100644 index 60549be5..00000000 --- a/external/tellstick-rfcmd/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/external/tellstick-rfcmd/Makefile b/external/tellstick-rfcmd/Makefile deleted file mode 100644 index 4836075a..00000000 --- a/external/tellstick-rfcmd/Makefile +++ /dev/null @@ -1,22 +0,0 @@ - -SRCS= rfcmd.c ftdi.c -CFLAGS=-O2 -Wall -I/usr/local/include -LFLAGS= -L/usr/local/lib -R/usr/local/lib -#linux:LFLAGS=-Wl,-rpath,/usr/local/lib -LIBS= -lftdi -lusb -PROG= rfcmd -FT= find_telldus -OBJS= $(SRCS:.c=.o) -CC= gcc - -all: $(PROG) $(FT) - -$(PROG): $(OBJS) - $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LFLAGS) $(LIBS) - -rfcmd.o: rfcmd.c - -ftdi.o: ftdi.c - -$(FT): $(FT).c - $(CC) $(CFLAGS) -o $@ $(FT).c $(LFLAGS) $(LIBS) diff --git a/external/tellstick-rfcmd/build.sh b/external/tellstick-rfcmd/build.sh deleted file mode 100644 index fb5100b9..00000000 --- a/external/tellstick-rfcmd/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -e -make clean || { echo "Warning: make clean failed"; } -make || { echo "make failed"; exit 1; } -make install || { echo "make install failed"; exit 1; } -echo rfcmd built and installed! diff --git a/external/tellstick-rfcmd/find_telldus.c b/external/tellstick-rfcmd/find_telldus.c deleted file mode 100644 index 5c44915e..00000000 --- a/external/tellstick-rfcmd/find_telldus.c +++ /dev/null @@ -1,42 +0,0 @@ -/* find_all.c - - Example for ftdi_usb_find_all() - - This program is distributed under the GPL, version 2 -*/ - -#include -#include - -int main(int argc, char **argv) -{ - int ret, i; - struct ftdi_context ftdic; - struct ftdi_device_list *devlist, *curdev; - char manufacturer[128], description[128]; - - ftdi_init(&ftdic); - - if((ret = ftdi_usb_find_all(&ftdic, &devlist, 0x1781, 0x0c30)) < 0) { - fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); - return EXIT_FAILURE; - } - - printf("Number of FTDI devices (telldus) found: %d\n", ret); - - i = 0; - for (curdev = devlist; curdev != NULL; i++) { - printf("Checking device: %d\n", i); - if((ret = ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) { - fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); - return EXIT_FAILURE; - } - printf("Manufacturer: %s, Description: %s\n\n", manufacturer, description); - curdev = curdev->next; - } - - ftdi_list_free(&devlist); - ftdi_deinit(&ftdic); - - return EXIT_SUCCESS; -} diff --git a/external/tellstick-rfcmd/ftdi.c b/external/tellstick-rfcmd/ftdi.c deleted file mode 100644 index 566311c7..00000000 --- a/external/tellstick-rfcmd/ftdi.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * TellStick libftdi libusb version - * tested with 0.15 : http://www.intra2net.com/en/developer/libftdi - */ - -#include -#include -#include -#include - -#define BAUD 4800 - -void ftdiCleanup(struct ftdi_context *ctx) { - ftdi_usb_close( ctx ); - ftdi_deinit( ctx ); -} - -/* - * use libftdi and libusb to send command - * no kernel driver needed - */ -int usbWriteFtdi(char *cmdstr) -{ - struct ftdi_context ctx; - int device=0x0c30, vendor=0x1781; - int retrycnt; - int retval = 0; - - if (ftdi_init( &ctx )) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - init error: %s\n", err); - return 1; - } - - retval = ftdi_usb_open(&ctx, vendor, device); - if (retval) { - char *err = ftdi_get_error_string(&ctx); - // FreeBSD says -3 when another rfcmd is running... - // Same on other systems? - if (retval == -3) { - fprintf(stderr, "usb - open error: %s. Is it busy?\n", err); - } else { - fprintf(stderr, "usb - open error: %s\n", err); - } - - ftdi_deinit( &ctx ); - return 2; - } - - if (ftdi_usb_reset( &ctx )) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - reset error: %s\n", err); - retval = 3; - ftdiCleanup(&ctx); - return retval; - } - - if (ftdi_disable_bitbang( &ctx ) || ftdi_set_baudrate(&ctx, BAUD)) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - init failed: %s\n", err); - ftdiCleanup(&ctx); - return 4; - } - - retval = ftdi_write_data( &ctx, cmdstr, strlen(cmdstr) ); - if (retval < 0) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - write failed: %s\n", err); - ftdiCleanup(&ctx); - return 5; - } else if (retval != strlen(cmdstr)) { - fprintf(stderr, "usb - warning: %d bytes written instead of %d\n", - retval, (int)strlen(cmdstr)); - } - - /** - * Wait for Tellstick to be done with cmd, read back until we've received - * a \n indicating end of response. - * Wait max 5000 * 1000uS. - * XXX: Can the tellstick report errors? - */ - retval = 0; - retrycnt = 5000; - while (retrycnt--) { - unsigned char inb; - int bytes; - - bytes = ftdi_read_data(&ctx, &inb, 1); - if (bytes == 0) { - usleep(1000); - } else if (bytes > 0) { - // Done when newline is received - if (inb == '\n') { - ftdiCleanup(&ctx); - return retval; - } - } else { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - read error: %s\n", err); - ftdiCleanup(&ctx); - return 6; - } - } - - // if we get here we failed to readback - fprintf(stderr, "usb - warning: never got newline response, giving up on wait\n"); - return retval; -} - - diff --git a/external/tellstick-rfcmd/rfcmd.c b/external/tellstick-rfcmd/rfcmd.c deleted file mode 100644 index 48bb3987..00000000 --- a/external/tellstick-rfcmd/rfcmd.c +++ /dev/null @@ -1,663 +0,0 @@ -/**************************************************************************** - ** rfcmd.c *********************************************************** - **************************************************************************** - * - * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick - * USB interface - * - * Copyright (C) 2007 Tord Andersson - * - * License: GPL v. 2 - * - * Authors: - * Tord Andersson - * Micke Prag - * Gudmund Berggren - * - * Tapani Rintala / userspace libusb / libftdi - version 02-2009 - */ - -/******************************************************************************* - * Modifications from rfcmd.c ver 0.2 done by Gudmund - * Added support for IKEA - * Note: - * 1. System code - * 2. Level 0 == Off (For dimmers and non dimmers) - * Level 1== 10%. (for dimmers) - * .... - * Level 9 == 90 % (for dimmers) - * Level 10 == 100 % (or ON for non dimmers) - * 3. Command line syntax: - * /usr/local/bin/rfcmd /dev/ttyUSB0 IKEA 0 1 10 1" - * Arg 1: device - * Arg 2: Protocoll - * Arg 3: System code - * Arg 4: Device code - * Arg 5: Level (0=off, 1 = 10%, 2=20%,...9=90%, 10=100%) - * Arg 6: DimStyle (0=instant change, 1=gradually change) - ******************************************************************************/ - -/******************************************************************************* - * Modifications to rfcmd.c ver 2.1.0 done by Tord Andersson - * Introduced semaphore protection to avoid problems with simultaneous port - * access from several processes (typically cron jobs). Note! Need rt lib. - ******************************************************************************/ - -/******************************************************************************* - * Modifications from rfcmd.c ver 2.1.0 done by Leo - * Added support for RISINGSUN - * Note: - * 1. Command line syntax: - * /usr/local/bin/rfcmd /dev/ttyUSB0 RISINGSUN 4 1 0" - * Arg 1: device - * Arg 2: protocol - * Arg 3: code - * Arg 4: device number - * Arg 5: Level (0=off, 1 = on) - ******************************************************************************/ - -/******************************************************************************* - * Modifications from rfcmd.c ver 2.1.0 based on marvelous work by Snakehand - * See http://www.telldus.com/forum/viewtopic.php?t=97&start=63 - * Added support for EVERFLOURISH - * Note: - * 1. Command line syntax: - * /usr/local/bin/rfcmd /dev/ttyUSB0 EVERFLOURISH 1 15 - * Arg 1: device - * Arg 2: protocol - * Arg 3: device number (0..65535) - * Arg 4: Level (0=off, 15=on, 10=learn) - ******************************************************************************/ - -/******************************************************************************* - * Modifications from rfcmd ver 2.1.1 done by Johan Str�m - * Default disabled semaphores for FreeBSD. - * Added status readback in ftdi.c, instead of wasting time in sleep. - * - * FreeBSD does not have support in the GENERIC kernel semaphore. - * To enable usage of them, you'll have have the following option in your - * kernel configuration: - * - * options P1003_1B_SEMAPHORES - * - * However, on FreeBSD only libftdi seems to be working (at least on my system), - * since the device is not identified as a ucom device. And as we're accessing it - * via libftdi, libftdi makes sure simultaneous access is impossible. - ******************************************************************************/ - - -#include -#include -#include -#include -#include -#include - -#ifndef NO_SEMAPHORES -#include -#endif - -#define PROG_NAME "rfcmd" -#define PROG_VERSION "2.1.1" -/* #define RFCMD_DEBUG */ - -/* Local function declarations */ -int createNexaString(const char * pHouseStr, const char * pChannelStr, - const char * pOn_offStr, char * pTxStr, int waveman); -int createSartanoString(const char * pChannelStr, const char * pOn_offStr, - char * pTxStr); -int createIkeaString(const char * pSystemStr, const char * pChannelStr, - const char * pLevelStr, const char *pDimStyle, - char * pStrReturn); -int createRisingSunString(const char * pCodeStr, const char* pUnitStr, const char * pOn_offStr, - char * pTxStr); -int createEverFlourishString(const char* pUnitStr, const char * pLevelStr, - char * pTxStr); -void printUsage(void); -void printVersion(void); - -#ifdef LIBFTDI -int usbWriteFtdi(char *cmdstr); -#endif - -int main( int argc, char **argv ) -{ - struct termios tio; - int fd = -1; -#ifndef NO_SEMAPHORES - sem_t * portMutex; - char SEM_NAME[]= "RFCMD_SEM"; /* Semaphore for multiple access ctrl */ -#endif - - - char txStr[100]; - - if ((argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) { - if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) { - if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) { - printUsage(); - exit(1); - } - } else if ( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) { - if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) { - // System, Channel, Level, DimStyle, TXString - if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc == 6) && (strcmp(*(argv+2),"RISINGSUN")==0) ) { - // Code, Unit, Power - if ( createRisingSunString(*(argv+3), *(argv+4), *(argv+5), txStr) == 0 ) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc == 5) && (strcmp(*(argv+2),"EVERFLOURISH")==0) ) { - // Unit, Level - if ( createEverFlourishString(*(argv+3), *(argv+4), txStr) == 0 ) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc >= 2) && (strcmp(*(argv+1),"--version")==0) ) { - printVersion(); - exit(1); - } else { /* protocol or parameters not recognized */ - printUsage(); - exit(1); - } - -#ifdef RFCMD_DEBUG - printf("txStr: %s\n", txStr); - -#endif - - if (strlen(txStr) > 0) { -#ifndef NO_SEMAPHORES - /* create the semaphore - will reuse an existing one if it exists */ - portMutex = sem_open(SEM_NAME,O_CREAT,0644,1); - if (portMutex == SEM_FAILED) { - fprintf(stderr, "%s - Error creating port semaphore\n", PROG_NAME); - perror("Semaphore open error"); - sem_unlink(SEM_NAME); - exit(1); - } - - /* lock semaphore to protect port from multiple access */ - if (sem_wait(portMutex) != 0) { - fprintf(stderr, "%s - Error aquiring port semaphore\n", PROG_NAME); - sem_unlink(SEM_NAME); - sem_close(portMutex); - exit(1); - } -#endif - - - if (strcmp(*(argv+1), "LIBUSB") != 0) { - if ( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) { -#ifdef __FreeBSD__ - fprintf(stderr, "%s - Error opening %s; You're on a FreeBSD system, you should probably use LIBUSB.\n", PROG_NAME, *(argv+1)); -#else - fprintf(stderr, "%s - Error opening %s\n", PROG_NAME, *(argv+1)); -#endif -#ifndef NO_SEMAPHORES - if (sem_post(portMutex) != 0) { - fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME); - } - sem_unlink(SEM_NAME); - sem_close(portMutex); -#endif - exit(1); - } - - /* adjust serial port parameters */ - bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ - tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ - tio.c_iflag = IGNPAR; - tio.c_oflag = 0; - tio.c_ispeed = 4800; - tio.c_ospeed = 4800; - tcflush(fd, TCIFLUSH); - tcsetattr(fd,TCSANOW,&tio); - - write(fd, txStr, strlen(txStr)); - - sleep(1); /* one second sleep to avoid device 'choking' */ - close(fd); /* Modified : Close fd to make a clean exit */ - } else { -#ifdef LIBFTDI - usbWriteFtdi( txStr ); -#else - fprintf(stderr, "%s - Support for libftdi is not compiled in, please recompile rfcmd with support for libftdi\n", PROG_NAME); -#endif - } -#ifndef NO_SEMAPHORES - /* Unlock semaphore */ - if (sem_post(portMutex) != 0) { - fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME); - sem_unlink(SEM_NAME); - sem_close(portMutex); - exit(1); - } else { - sem_unlink(SEM_NAME); - sem_close(portMutex); - } -#endif - } - exit(0); -} - - -int createNexaString(const char * pHouseStr, const char * pChannelStr, - const char * pOn_offStr, char * pTxStr, int waveman) -{ - * pTxStr = '\0'; /* Make sure tx string is empty */ - int houseCode; - int channelCode; - int on_offCode; - int txCode = 0; - const int unknownCode = 0x6; - int bit; - int bitmask = 0x0001; - - houseCode = (int)((* pHouseStr) - 65); /* House 'A'..'P' */ - channelCode = atoi(pChannelStr) - 1; /* Channel 1..16 */ - on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ - -#ifdef RFCMD_DEBUG - printf("House: %d, channel: %d, on_off: %d\n", houseCode, channelCode, on_offCode); -#endif - - /* check converted parameters for validity */ - if((houseCode < 0) || (houseCode > 15) || // House 'A'..'P' - (channelCode < 0) || (channelCode > 15) || - (on_offCode < 0) || (on_offCode > 1)) - { - - } else { - /* b0..b11 txCode where 'X' will be represented by 1 for simplicity. - b0 will be sent first */ - txCode = houseCode; - txCode |= (channelCode << 4); - if (waveman && on_offCode == 0) { - } else { - txCode |= (unknownCode << 8); - txCode |= (on_offCode << 11); - } - - /* convert to send cmd string */ - strcat(pTxStr,"S"); - for(bit=0;bit<12;bit++) - { - if((bitmask & txCode) == 0) { - /* bit timing might need further refinement */ - strcat(pTxStr," ` `"); /* 320 us high, 960 us low, 320 us high, 960 us low */ - /* strcat(pTxStr,"$k$k"); *//* 360 us high, 1070 us low, 360 us high, 1070 us low */ - } else { /* add 'X' (floating bit) */ - strcat(pTxStr," `` "); /* 320 us high, 960 us low, 960 us high, 320 us low */ - /*strcat(pTxStr,"$kk$"); *//* 360 us high, 1070 us low, 1070 us high, 360 us low */ - } - bitmask = bitmask<<1; - } - /* add stop/sync bit and command termination char '+'*/ - strcat(pTxStr," }+"); - /* strcat(pTxStr,"$}+"); */ - } - -#ifdef RFCMD_DEBUG - printf("txCode: %04X\n", txCode); -#endif - - return strlen(pTxStr); -} - -int createSartanoString(const char * pChannelStr, const char * pOn_offStr, - char * pTxStr) -{ - * pTxStr = '\0'; /* Make sure tx string is empty */ - int on_offCode; - int bit; - - on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ - -#ifdef RFCMD_DEBUG - printf("Channel: %s, on_off: %d\n", pChannelStr, on_offCode); -#endif - - /* check converted parameters for validity */ - if((strlen(pChannelStr) != 10) || - (on_offCode < 0) || (on_offCode > 1)) { - } else { - strcat(pTxStr,"S"); - for(bit=0;bit<=9;bit++) - { - if (strncmp(pChannelStr+bit, "1", 1) == 0) { //If it is a "1" - strcat(pTxStr,"$k$k"); - } else { - strcat(pTxStr,"$kk$"); - } - } - if (on_offCode >= 1) - strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code - else - strcat(pTxStr,"$kk$$k$k"); //the "turn off"-code - - /* add stop/sync bit and command termination char '+'*/ - strcat(pTxStr,"$k+"); - } - - return strlen(pTxStr); -} - -int createIkeaString( const char * pSystemStr, const char * pChannelStr, const char * pLevelStr, const char *pDimStyle, char * pStrReturn) -{ - *pStrReturn = '\0'; /* Make sure tx string is empty */ - - const char STARTCODE[] = "STTTTTT�"; - const char TT[] = "TT"; - const char A[] = "�"; - int systemCode = atoi(pSystemStr) - 1; /* System 1..16 */ - int channelCode = atoi(pChannelStr); /* Channel 1..10 */ - int Level = atoi(pLevelStr); /* off,10,20,..,90,on */ - int DimStyle = atoi(pDimStyle); - int intCode = 0; - int checksum1 = 0; - int checksum2 = 0; - int intFade ; - int i ; - int rawChannelCode = 0; - - /* check converted parameters for validity */ - if ( (channelCode <= 0) || (channelCode > 10) || - (systemCode < 0) || (systemCode > 15) || - (Level < 0) || (Level > 10) || - (DimStyle < 0) || (DimStyle > 1)) - { - return 0; - } - - if (channelCode == 10) { - channelCode = 0; - } - rawChannelCode = (1<<(9-channelCode)); - - strcat(pStrReturn, STARTCODE ) ; //Startcode, always like this; - intCode = (systemCode << 10) | rawChannelCode; - - for ( i = 13; i >= 0; --i) { - if ((intCode>>i) & 1) { - strcat(pStrReturn, TT ); - if (i % 2 == 0) { - checksum2++; - } else { - checksum1++; - } - } else { - strcat(pStrReturn,A); - } - } - - if (checksum1 %2 == 0) { - strcat(pStrReturn, TT ); - } else { - strcat(pStrReturn, A) ; //1st checksum - } - - if (checksum2 %2 == 0) { - strcat(pStrReturn, TT ); - } else { - strcat(pStrReturn, A ) ; //2nd checksum - } - - if (DimStyle == 1) { - intFade = 11 << 4; //Smooth - } else { - intFade = 1 << 4; //Instant - } - - switch ( Level ) - { - case 0 : - intCode = (10 | intFade) ; //Concat level and fade - break; - case 1 : - intCode = (1 | intFade) ; //Concat level and fade - break; - case 2 : - intCode = (2 | intFade) ; //Concat level and fade - break; - case 3 : - intCode = (3 | intFade) ; //Concat level and fade - break; - case 4 : - intCode = (4 | intFade) ; //Concat level and fade - break; - case 5 : - intCode = (5 | intFade) ; //Concat level and fade - break; - case 6 : - intCode = (6 | intFade) ; //Concat level and fade - break; - case 7 : - intCode = (7 | intFade) ; //Concat level and fade - break; - case 8 : - intCode = (8 | intFade) ; //Concat level and fade - break; - case 9 : - intCode = (9 | intFade) ; //Concat level and fade - break; - case 10 : - default : - intCode = (0 | intFade) ; //Concat level and fade - break; - } - - checksum1 = 0; - checksum2 = 0; - - for (i = 0; i < 6; ++i) { - if ((intCode>>i) & 1) { - strcat(pStrReturn, TT); - - if (i % 2 == 0) { - checksum1++; - } else { - checksum2++; - } - } else { - strcat(pStrReturn, A ); - } - } - - if (checksum1 %2 == 0) { - strcat(pStrReturn, TT); - } else { - strcat(pStrReturn, A ) ; //2nd checksum - } - - if (checksum2 %2 == 0) { - strcat(pStrReturn, TT ); - } else { - strcat(pStrReturn, A ) ; //2nd checksum - } - - strcat(pStrReturn, "+"); - - return strlen(pStrReturn); -} - -int createRisingSunString(const char * pCodeStr, const char * pUnitStr, const char * pOn_offStr, - char * pTxStr) -{ - * pTxStr = '\0'; /* Make sure tx string is empty */ - int on_offCode; - int unit; - int code; - int i; - - on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ - code = atoi (pCodeStr); - unit = atoi (pUnitStr); - -#ifdef RFCMD_DEBUG - printf("Code: %s, unit: %s, on_off: %d\n", pCodeStr, pUnitStr, on_offCode); -#endif - - /* check converted parameters for validity */ - if((code < 1) || (code > 4) || - (unit < 1) || (unit > 4) || - (on_offCode < 0) || (on_offCode > 1)) { - } else { - strcat(pTxStr,"S.e"); - for (i = 1; i <= 4; ++i) { - if (i == code) { - strcat (pTxStr, ".e.e"); - } else { - strcat (pTxStr, "e..e"); - } - } - for (i = 1; i <= 4; ++i) { - if (i == unit) { - strcat (pTxStr, ".e.e"); - } else { - strcat (pTxStr, "e..e"); - } - } - - if (on_offCode >= 1) { - strcat(pTxStr,"e..ee..ee..ee..e+"); //the "turn on"-code - } else { - strcat(pTxStr,"e..ee..ee..e.e.e+"); //the "turn off"-code - } - } - - return strlen(pTxStr); -} - -unsigned int everflourish_find_code(unsigned int x) { - unsigned int bits[16] = { 0xf ,0xa ,0x7 ,0xe, - 0xf ,0xd ,0x9 ,0x1, - 0x1 ,0x2 ,0x4 ,0x8, - 0x3 ,0x6 ,0xc ,0xb }; - unsigned int bit = 1; - unsigned int res = 0x5; - int i; - unsigned int lo,hi; - - if ((x&0x3)==3) { - lo = x & 0x00ff; - hi = x & 0xff00; - lo += 4; - if (lo>0x100) lo = 0x12; - x = lo | hi; - } - - for(i=0;i<16;i++) { - if (x&bit) { - res = res ^ bits[i]; - } - bit = bit << 1; - } - - return res; -} - - -int createEverFlourishString(const char * pUnitStr, const char * pLevelStr, - char * pTxStr) -{ - int len = 0; - int level; - int unit; - unsigned int check; - int i; - - unit = atoi(pUnitStr); - level = atoi(pLevelStr); /* ON=15, OFF=0, LEARN=10 */ - check = everflourish_find_code(unit); - -#ifdef RFCMD_DEBUG - printf("unit: %d, level: %d\n", unit, level); -#endif - - /* check converted parameters for validity */ - if((unit < 0) || (unit > 0xffff) || - (level < 0) || (level > 15)) { - } else { - const char ssss = 85; - const char sssl = 84; // 0 - const char slss = 69; // 1 - - const char bits[2] = {sssl,slss}; - int i; - - char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss}; - memcpy(pTxStr, preamble, sizeof(preamble)); - len += sizeof(preamble); - - for(i=15;i>=0;i--) pTxStr[len++]=bits[(unit>>i)&0x01]; - for(i=3;i>=0;i--) pTxStr[len++]=bits[(check>>i)&0x01]; - for(i=3;i>=0;i--) pTxStr[len++]=bits[(level>>i)&0x01]; - - pTxStr[len++] = ssss; - pTxStr[len++] = '+'; - } - - pTxStr[len] = '\0'; - return strlen(pTxStr); -} - -void printUsage(void) -{ - printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n"); - printf("\n"); -#ifdef LIBFTDI - printf("\t DEVICE: /dev/ttyUSB[0..n] | LIBUSB\n" ); -#else - printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); -#endif - printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA, RISINGSUN, EVERFLOURISH\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n"); - printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - SARTANO:\n"); - printf("\t\tCHANNEL: 0000000000..1111111111\n\t\tOFF_ON: 0..1\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - IKEA:\n"); - printf("\t\tSYSTEM: 1..16\n\t\tDEVICE: 1..10\n"); - printf("\t\tDIM_LEVEL: 0..10\n\t\tDIM_STYLE: 0..1\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - RISINGSUN:\n"); - printf("\t\tCODE: 1..4\n\t\tDEVICE: 1..4\n"); - printf("\t\tOFF_ON: 0..1\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - EVERFLOURISH:\n"); - printf("\t\tDEVICE: 0..65535\n"); - printf("\t\tLEVEL: 0=off, 10=learn, 15=on\n" ); - printf("\n"); - printf("Report bugs to \n"); -} - -void printVersion(void) { - printf("%s v%s\n", PROG_NAME, PROG_VERSION); - printf("\n"); - printf("Copyright (C) Tord Andersson 2007\n"); - printf("\n"); - printf("Written by:\n"); - printf("Tord Andersson, Micke Prag, Gudmund Berggren, Tapani Rintala\n"); - printf("and Johan Str�m\n"); -} - diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 62d4c053..00000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a5952066..00000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100644 index fbd7c515..00000000 --- a/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 5093609d..00000000 --- a/gradlew.bat +++ /dev/null @@ -1,104 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/hal-core/build.gradle b/hal-core/build.gradle deleted file mode 100644 index a8a20ef8..00000000 --- a/hal-core/build.gradle +++ /dev/null @@ -1,26 +0,0 @@ -// ------------------------------------ -// Hal core configuration -// ------------------------------------ - -dependencies { - implementation 'org.xerial:sqlite-jdbc:3.42.0.1' - implementation 'org.shredzone.acme4j:acme4j-client:2.12' - implementation 'org.shredzone.acme4j:acme4j-utils:2.12' -} - -// Make test classes available to other projects - -configurations { - testClasses { - extendsFrom(testImplementation) - } -} - -task testJar(type: Jar) { - archiveClassifier.set('test') - from sourceSets.test.output -} - -artifacts { - testClasses testJar // add the jar generated by the testJar task to the testClasses dependency -} \ No newline at end of file diff --git a/hal-core/resources/hal-core-reference.db b/hal-core/resources/hal-core-reference.db deleted file mode 100644 index d18d7c30..00000000 Binary files a/hal-core/resources/hal-core-reference.db and /dev/null differ diff --git a/hal-core/resources/web/api/docs.html b/hal-core/resources/web/api/docs.html deleted file mode 100644 index a187ec73..00000000 --- a/hal-core/resources/web/api/docs.html +++ /dev/null @@ -1,25 +0,0 @@ - - - -Hal OpenAPI Documentation - - - - - - - -
- - \ No newline at end of file diff --git a/hal-core/resources/web/api/openapi.json b/hal-core/resources/web/api/openapi.json deleted file mode 100644 index a3dbf042..00000000 --- a/hal-core/resources/web/api/openapi.json +++ /dev/null @@ -1,313 +0,0 @@ -{ - "components": { - "schemas": { - "alertClass": { - "type": "object", - "properties": { - "id": {"type": "integer"}, - "level": {"type": "string"}, - "ttl": {"type": "integer"}, - "title": {"type": "string"}, - "description": {"type": "string"} - } - }, - - "eventClass": { - "type": "object", - "properties": { - "data": { - "type": "object", - "$ref": "#/components/schemas/dataClass" - }, - "dataType": {"type": "string"}, - "name": {"type": "string"}, - "id": {"type": "integer"}, - "map": { - "type": "object", - "$ref": "#/components/schemas/mapClass" - }, - "user": {"type": "string"}, - "config": { - "type": "object", - "$ref": "#/components/schemas/configClass" - }, - "configType": {"type": "string"} - } - }, - - "roomClass": { - "type": "object", - "properties": { - "id": {"type": "integer"}, - "name": {"type": "string"}, - "map": { - "type": "object", - "$ref": "#/components/schemas/mapClass" - } - } - }, - - "sensorClass": { - "type": "object", - "properties": { - "data": { - "type": "object", - "$ref": "#/components/schemas/dataClass" - }, - "name": {"type": "string"}, - "id": {"type": "integer"}, - "map": { - "type": "object", - "$ref": "#/components/schemas/mapClass" - }, - "user": {"type": "string"}, - "config": { - "type": "object", - "$ref": "#/components/schemas/configClass" - }, - "aggregate": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "number" - } - }, - "timestamps": { - "type": "array", - "items": { - "type": "integer" - } - } - } - } - } - }, - - "configClass": { - "type": "object", - "properties": { - } - }, - - "dataClass": { - "type": "object", - "properties": { - "valueStr": {"type": "string"}, - "value": {"type": "number"}, - "timestamp": {"type": "integer"} - } - }, - - "mapClass": { - "type": "object", - "properties": { - "x": {"type": "number"}, - "y": {"type": "number"}, - "width": {"type": "number"}, - "height": {"type": "number"} - } - }, - } - }, - - "servers": [ - { - "description": "Hal Server", - "url": "/api" - } - ], - - "openapi": "3.0.1", - - "paths": { - "/alert": { - "get": { - "responses": { - "200": { - "description": "A successful response.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/components/schemas/alertClass" - } - } - } - } - } - }, - "parameters": [ - { - "schema": { - "type": "string", - "enum": [ - "poll", - "peek", - "dismiss" - ] - }, - "in": "query", - "name": "action", - "required": true - }, - { - "schema": { - "type": "integer" - }, - "in": "query", - "name": "id", - "required": false - } - ] - } - }, - - "/event": { - "get": { - "responses": { - "200": { - "description": "A successful response.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/components/schemas/eventClass" - } - } - } - } - } - }, - "parameters": [ - { - "schema": { - "type": "integer" - }, - "in": "query", - "name": "id", - "required": false - }, - { - "schema": { - "type": "string" - }, - "in": "query", - "name": "configType", - "required": false - }, - { - "schema": { - "type": "string" - }, - "in": "query", - "name": "dataType", - "required": false - } - ] - } - }, - - "/room": { - "get": { - "responses": { - "200": { - "description": "A successful response.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/components/schemas/roomClass" - } - } - } - } - } - }, - "parameters": [ - { - "schema": { - "type": "integer" - }, - "in": "query", - "name": "id", - "required": false - } - ] - } - }, - - "/sensor": { - "get": { - "responses": { - "200": { - "description": "A successful response.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/components/schemas/sensorClass" - } - } - } - } - } - }, - "parameters": [ - { - "schema": { - "type": "integer" - }, - "in": "query", - "name": "id", - "required": false - }, - { - "schema": { - "type": "string" - }, - "in": "query", - "name": "configType", - "required": false - }, - { - "schema": { - "type": "string" - }, - "in": "query", - "name": "dataType", - "required": false - }, - { - "schema": { - "type": "string", - "enum": [ - "min", - "hour", - "day", - "week" - ] - }, - "in": "query", - "name": "aggregation", - "required": false - } - ] - } - } - }, - "info": { - "description": "This API allows developers and external tools to interface to Hal data and trigger different actions.", - "title": "Hal REST API", - "version": "" - } -} \ No newline at end of file diff --git a/hal-core/resources/web/css/hal.css b/hal-core/resources/web/css/hal.css deleted file mode 100644 index 030b1863..00000000 --- a/hal-core/resources/web/css/hal.css +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Base structure - */ - -/* Move down content because we have a fixed navbar that is 50px tall */ -body { - padding-top: 50px; -} - - -/* - * Global add-ons - */ - -.sub-header { - padding-bottom: 10px; - border-bottom: 1px solid #eee; -} - -/* - * Top navigation - * Hide default border to remove 1px line. - */ -.navbar-fixed-top { - border: 0; -} - -/* - * Sidebar - */ - -/* Hide for mobile, show later */ -.sidebar { - display: none; -} -@media (min-width: 768px) { - .sidebar { - position: fixed; - top: 51px; - bottom: 0; - left: 0; - z-index: 1000; - display: block; - padding: 20px; - overflow-x: hidden; - overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ - background-color: #f5f5f5; - border-right: 1px solid #eee; - } -} - -/* Sidebar navigation */ -.nav-sidebar { - margin-right: -21px; /* 20px padding + 1px border */ - margin-bottom: 20px; - margin-left: -20px; -} -.nav-sidebar > li > a { - padding-right: 20px; - padding-left: 20px; -} -.nav-sidebar > .active > a, -.nav-sidebar > .active > a:hover, -.nav-sidebar > .active > a:focus { - color: #fff; - background-color: #428bca; -} - - -/* - * Main content - */ - -.main { - padding: 20px; -} -@media (min-width: 768px) { - .main { - padding-right: 40px; - padding-left: 40px; - } -} -.main .page-header { - margin-top: 0; -} - -.vertical-space { - height: 70px; -} -.text-vert-middle { - vertical-align: middle !important; -} - -.table-borderless tbody tr td { - border: none; -} - -.drop-shadow { - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12) -} - -.disabled { - background-color: lightgray; - opacity: .6; -} - -/* - * Placeholder dashboard ideas - */ - -.placeholders { - margin-bottom: 150px; - text-align: center; -} -.placeholders h4 { - margin-bottom: 0; -} -.placeholder { - margin-bottom: 20px; -} -.placeholder img { - display: inline-block; - border-radius: 50%; -} - - -/* - * c3.js charts overrides - */ -.c3 line, .c3 path { - stroke: #ccc; -} -.c3-line { - stroke-width: 2px; -} - - -.anim-spin { - animation: spin 2s infinite linear; -} -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(359deg); - } -} - -/* - * Animations - */ - -.pulse-border { - animation: pulse 2s infinite; -} - -@keyframes pulse { - 0% { - stroke-width: 3; - opacity: 1; - } - - 10% { - stroke-width: 5; - opacity: 0.2; - } - 15% { - stroke-width: 5; - opacity: 0.2; - } - - 50% { - stroke-width: 3; - opacity: 1; - } - - 100% { - stroke-width: 3; - opacity: 1; - } -} - -/* - * Switch checkbox CSS, originally from: - * https://community.tadabase.io/t/convert-checkbox-to-toggle-switch/2566 - */ - -input[type="checkbox"].switch { - /* Backgrpund properties */ - appearance: none; - background-color: #e1e1e1; /* unchecked background color */ - border-radius: 72px; - border-style: none; - flex-shrink: 0; - position: relative; - cursor: pointer; - margin: 0 !important; - width: 40px !important; - height: 20px !important; - border: 1px solid #ccc; -} -input[type="checkbox"].switch, -input[type="checkbox"].switch::after { - transition: all 100ms ease-out; -} -input[type="checkbox"].switch::after { - /* Ball properties */ - background-color: #fff; /* Color of ball */ - border-radius: 50%; - content: ""; - height: 15px !important; - width: 15px !important; - left: 3px !important; - top: 2px !important; - position: absolute; -} -/* Properties for a checked state */ -input[type="checkbox"].switch:checked { - background-color: #d9534f; /* Color of background */ -} -input[type="checkbox"].switch:checked::after { - background-color: #fff; /* Color of ball */ - left: 20px !important; -} - -/* - * Slider styling - */ - -input[type="range"] { - accent-color: #d9534f; -} diff --git a/hal-core/resources/web/css/lib/bootstrap-switch.css b/hal-core/resources/web/css/lib/bootstrap-switch.css deleted file mode 100644 index 608fc698..00000000 --- a/hal-core/resources/web/css/lib/bootstrap-switch.css +++ /dev/null @@ -1,187 +0,0 @@ -/** - * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches. - * - * @version v3.3.4 - * @homepage https://bttstrp.github.io/bootstrap-switch - * @author Mattia Larentis (http://larentis.eu) - * @license Apache-2.0 - */ - -.bootstrap-switch { - display: inline-block; - direction: ltr; - cursor: pointer; - border-radius: 4px; - border: 1px solid; - border-color: #ccc; - position: relative; - text-align: left; - overflow: hidden; - line-height: 8px; - z-index: 0; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - vertical-align: middle; - -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - -o-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; -} -.bootstrap-switch .bootstrap-switch-container { - display: inline-block; - top: 0; - border-radius: 4px; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} -.bootstrap-switch .bootstrap-switch-handle-on, -.bootstrap-switch .bootstrap-switch-handle-off, -.bootstrap-switch .bootstrap-switch-label { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - cursor: pointer; - display: table-cell; - vertical-align: middle; - padding: 6px 12px; - font-size: 14px; - line-height: 20px; -} -.bootstrap-switch .bootstrap-switch-handle-on, -.bootstrap-switch .bootstrap-switch-handle-off { - text-align: center; - z-index: 1; -} -.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, -.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary { - color: #fff; - background: #337ab7; -} -.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info, -.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info { - color: #fff; - background: #5bc0de; -} -.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success, -.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success { - color: #fff; - background: #5cb85c; -} -.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning, -.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning { - background: #f0ad4e; - color: #fff; -} -.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger, -.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger { - color: #fff; - background: #d9534f; -} -.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default, -.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default { - color: #000; - background: #eeeeee; -} -.bootstrap-switch .bootstrap-switch-label { - text-align: center; - margin-top: -1px; - margin-bottom: -1px; - z-index: 100; - color: #333; - background: #fff; -} -.bootstrap-switch span::before { - content: "\200b"; -} -.bootstrap-switch .bootstrap-switch-handle-on { - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; -} -.bootstrap-switch .bootstrap-switch-handle-off { - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; -} -.bootstrap-switch input[type='radio'], -.bootstrap-switch input[type='checkbox'] { - position: absolute !important; - top: 0; - left: 0; - margin: 0; - z-index: -1; - opacity: 0; - filter: alpha(opacity=0); - visibility: hidden; -} -.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on, -.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off, -.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; -} -.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on, -.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off, -.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; -} -.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on, -.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off, -.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label { - padding: 6px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.bootstrap-switch.bootstrap-switch-disabled, -.bootstrap-switch.bootstrap-switch-readonly, -.bootstrap-switch.bootstrap-switch-indeterminate { - cursor: default !important; -} -.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on, -.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on, -.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on, -.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off, -.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off, -.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off, -.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label, -.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label, -.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label { - opacity: 0.5; - filter: alpha(opacity=50); - cursor: default !important; -} -.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container { - -webkit-transition: margin-left 0.5s; - -o-transition: margin-left 0.5s; - transition: margin-left 0.5s; -} -.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; -} -.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; -} -.bootstrap-switch.bootstrap-switch-focused { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); -} -.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label, -.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label { - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; -} -.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label, -.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label { - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; -} diff --git a/hal-core/resources/web/css/lib/bootstrap-switch.min.css b/hal-core/resources/web/css/lib/bootstrap-switch.min.css deleted file mode 100644 index 77006595..00000000 --- a/hal-core/resources/web/css/lib/bootstrap-switch.min.css +++ /dev/null @@ -1,10 +0,0 @@ -/** - * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches. - * - * @version v3.3.4 - * @homepage https://bttstrp.github.io/bootstrap-switch - * @author Mattia Larentis (http://larentis.eu) - * @license Apache-2.0 - */ - -.bootstrap-switch{display:inline-block;direction:ltr;cursor:pointer;border-radius:4px;border:1px solid #ccc;position:relative;text-align:left;overflow:hidden;line-height:8px;z-index:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-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}.bootstrap-switch .bootstrap-switch-container{display:inline-block;top:0;border-radius:4px;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on,.bootstrap-switch .bootstrap-switch-label{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:table-cell;vertical-align:middle;padding:6px 12px;font-size:14px;line-height:20px}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on{text-align:center;z-index:1}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary{color:#fff;background:#337ab7}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info{color:#fff;background:#5bc0de}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success{color:#fff;background:#5cb85c}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning{background:#f0ad4e;color:#fff}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger{color:#fff;background:#d9534f}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default{color:#000;background:#eee}.bootstrap-switch .bootstrap-switch-label{text-align:center;margin-top:-1px;margin-bottom:-1px;z-index:100;color:#333;background:#fff}.bootstrap-switch span::before{content:"\200b"}.bootstrap-switch .bootstrap-switch-handle-on{border-bottom-left-radius:3px;border-top-left-radius:3px}.bootstrap-switch .bootstrap-switch-handle-off{border-bottom-right-radius:3px;border-top-right-radius:3px}.bootstrap-switch input[type=radio],.bootstrap-switch input[type=checkbox]{position:absolute!important;top:0;left:0;margin:0;z-index:-1;opacity:0;filter:alpha(opacity=0);visibility:hidden}.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label{padding:1px 5px;font-size:12px;line-height:1.5}.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label{padding:5px 10px;font-size:12px;line-height:1.5}.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label{padding:6px 16px;font-size:18px;line-height:1.3333333}.bootstrap-switch.bootstrap-switch-disabled,.bootstrap-switch.bootstrap-switch-indeterminate,.bootstrap-switch.bootstrap-switch-readonly{cursor:default!important}.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label{opacity:.5;filter:alpha(opacity=50);cursor:default!important}.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container{-webkit-transition:margin-left .5s;-o-transition:margin-left .5s;transition:margin-left .5s}.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on{border-radius:0 3px 3px 0}.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off{border-radius:3px 0 0 3px}.bootstrap-switch.bootstrap-switch-focused{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)}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label{border-bottom-right-radius:3px;border-top-right-radius:3px}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label{border-bottom-left-radius:3px;border-top-left-radius:3px} \ No newline at end of file diff --git a/hal-core/resources/web/css/lib/bootstrap-theme.css b/hal-core/resources/web/css/lib/bootstrap-theme.css deleted file mode 100644 index 31d88826..00000000 --- a/hal-core/resources/web/css/lib/bootstrap-theme.css +++ /dev/null @@ -1,587 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 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-default.disabled, -.btn-primary.disabled, -.btn-success.disabled, -.btn-info.disabled, -.btn-warning.disabled, -.btn-danger.disabled, -.btn-default[disabled], -.btn-primary[disabled], -.btn-success[disabled], -.btn-info[disabled], -.btn-warning[disabled], -.btn-danger[disabled], -fieldset[disabled] .btn-default, -fieldset[disabled] .btn-primary, -fieldset[disabled] .btn-success, -fieldset[disabled] .btn-info, -fieldset[disabled] .btn-warning, -fieldset[disabled] .btn-danger { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-default .badge, -.btn-primary .badge, -.btn-success .badge, -.btn-info .badge, -.btn-warning .badge, -.btn-danger .badge { - text-shadow: none; -} -.btn:active, -.btn.active { - background-image: none; -} -.btn-default { - text-shadow: 0 1px 0 #fff; - background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); - 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; - 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-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.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: #e0e0e0; - background-image: none; -} -.btn-primary { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); - background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #245580; -} -.btn-primary:hover, -.btn-primary:focus { - background-color: #265a88; - background-position: 0 -15px; -} -.btn-primary:active, -.btn-primary.active { - background-color: #265a88; - border-color: #245580; -} -.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.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: #265a88; - background-image: none; -} -.btn-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); - 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-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.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: #419641; - background-image: none; -} -.btn-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); - 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-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.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: #2aabd2; - background-image: none; -} -.btn-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); - 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-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.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: #eb9316; - background-image: none; -} -.btn-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); - 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; -} -.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.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: #c12e2a; - background-image: none; -} -.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-color: #e8e8e8; - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - background-color: #2e6da4; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; -} -.navbar-default { - background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); - background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - 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 > .open > a, -.navbar-default .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); - background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); - background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); - background-repeat: repeat-x; - -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: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); - background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-radius: 4px; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); - background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); - background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); - background-repeat: repeat-x; - -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; -} -@media (max-width: 767px) { - .navbar .navbar-nav .open .dropdown-menu > .active > a, - .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; - } -} -.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: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); - background-repeat: repeat-x; - border-color: #b2dba1; -} -.alert-info { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); - background-repeat: repeat-x; - border-color: #9acfea; -} -.alert-warning { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); - background-repeat: repeat-x; - border-color: #f5e79e; -} -.alert-danger { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); - background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); - background-repeat: repeat-x; - border-color: #dca7a7; -} -.progress { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); - background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-striped { - 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: -o-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); -} -.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 #286090; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); - background-repeat: repeat-x; - border-color: #2b669a; -} -.list-group-item.active .badge, -.list-group-item.active:hover .badge, -.list-group-item.active:focus .badge { - text-shadow: none; -} -.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: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; -} -.panel-primary > .panel-heading { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; -} -.panel-success > .panel-heading { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); - background-repeat: repeat-x; -} -.panel-info > .panel-heading { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); - background-repeat: repeat-x; -} -.panel-warning > .panel-heading { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); - background-repeat: repeat-x; -} -.panel-danger > .panel-heading { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); - background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); - background-repeat: repeat-x; -} -.well { - background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; - 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); -} -/*# sourceMappingURL=bootstrap-theme.css.map */ diff --git a/hal-core/resources/web/css/lib/bootstrap-theme.min.css b/hal-core/resources/web/css/lib/bootstrap-theme.min.css deleted file mode 100644 index 5e394019..00000000 --- a/hal-core/resources/web/css/lib/bootstrap-theme.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{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-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning: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-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));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;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));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:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));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:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));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:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));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:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.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:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;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,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-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:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-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-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.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:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{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:-o-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)}.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:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.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:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;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)} -/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/hal-core/resources/web/css/lib/bootstrap.css b/hal-core/resources/web/css/lib/bootstrap.css deleted file mode 100644 index 8176de13..00000000 --- a/hal-core/resources/web/css/lib/bootstrap.css +++ /dev/null @@ -1,6757 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -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-color: transparent; -} -a:active, -a:hover { - outline: 0; -} -abbr[title] { - border-bottom: 1px dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -h1 { - margin: .67em 0; - font-size: 2em; -} -mark { - color: #000; - background: #ff0; -} -small { - font-size: 80%; -} -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sup { - top: -.5em; -} -sub { - bottom: -.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 1em 40px; -} -hr { - height: 0; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -pre { - overflow: auto; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -button, -input, -optgroup, -select, -textarea { - margin: 0; - font: inherit; - color: inherit; -} -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 { - padding: 0; - border: 0; -} -input { - line-height: normal; -} -input[type="checkbox"], -input[type="radio"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - 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-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid #c0c0c0; -} -legend { - padding: 0; - border: 0; -} -textarea { - overflow: auto; -} -optgroup { - font-weight: bold; -} -table { - border-spacing: 0; - border-collapse: collapse; -} -td, -th { - padding: 0; -} -/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ -@media print { - *, - *:before, - *:after { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - -webkit-box-shadow: none !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^="#"]:after, - a[href^="javascript:"]: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; - } - .navbar { - display: none; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table td, - .table th { - background-color: #fff !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} -@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.woff2') format('woff2'), 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: normal; - line-height: 1; - - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.glyphicon-asterisk:before { - content: "\002a"; -} -.glyphicon-plus:before { - content: "\002b"; -} -.glyphicon-euro:before, -.glyphicon-eur: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"; -} -.glyphicon-cd:before { - content: "\e201"; -} -.glyphicon-save-file:before { - content: "\e202"; -} -.glyphicon-open-file:before { - content: "\e203"; -} -.glyphicon-level-up:before { - content: "\e204"; -} -.glyphicon-copy:before { - content: "\e205"; -} -.glyphicon-paste:before { - content: "\e206"; -} -.glyphicon-alert:before { - content: "\e209"; -} -.glyphicon-equalizer:before { - content: "\e210"; -} -.glyphicon-king:before { - content: "\e211"; -} -.glyphicon-queen:before { - content: "\e212"; -} -.glyphicon-pawn:before { - content: "\e213"; -} -.glyphicon-bishop:before { - content: "\e214"; -} -.glyphicon-knight:before { - content: "\e215"; -} -.glyphicon-baby-formula:before { - content: "\e216"; -} -.glyphicon-tent:before { - content: "\26fa"; -} -.glyphicon-blackboard:before { - content: "\e218"; -} -.glyphicon-bed:before { - content: "\e219"; -} -.glyphicon-apple:before { - content: "\f8ff"; -} -.glyphicon-erase:before { - content: "\e221"; -} -.glyphicon-hourglass:before { - content: "\231b"; -} -.glyphicon-lamp:before { - content: "\e223"; -} -.glyphicon-duplicate:before { - content: "\e224"; -} -.glyphicon-piggy-bank:before { - content: "\e225"; -} -.glyphicon-scissors:before { - content: "\e226"; -} -.glyphicon-bitcoin:before { - content: "\e227"; -} -.glyphicon-btc:before { - content: "\e227"; -} -.glyphicon-xbt:before { - content: "\e227"; -} -.glyphicon-yen:before { - content: "\00a5"; -} -.glyphicon-jpy:before { - content: "\00a5"; -} -.glyphicon-ruble:before { - content: "\20bd"; -} -.glyphicon-rub:before { - content: "\20bd"; -} -.glyphicon-scale:before { - content: "\e230"; -} -.glyphicon-ice-lolly:before { - content: "\e231"; -} -.glyphicon-ice-lolly-tasted:before { - content: "\e232"; -} -.glyphicon-education:before { - content: "\e233"; -} -.glyphicon-option-horizontal:before { - content: "\e234"; -} -.glyphicon-option-vertical:before { - content: "\e235"; -} -.glyphicon-menu-hamburger:before { - content: "\e236"; -} -.glyphicon-modal-window:before { - content: "\e237"; -} -.glyphicon-oil:before { - content: "\e238"; -} -.glyphicon-grain:before { - content: "\e239"; -} -.glyphicon-sunglasses:before { - content: "\e240"; -} -.glyphicon-text-size:before { - content: "\e241"; -} -.glyphicon-text-color:before { - content: "\e242"; -} -.glyphicon-text-background:before { - content: "\e243"; -} -.glyphicon-object-align-top:before { - content: "\e244"; -} -.glyphicon-object-align-bottom:before { - content: "\e245"; -} -.glyphicon-object-align-horizontal:before { - content: "\e246"; -} -.glyphicon-object-align-left:before { - content: "\e247"; -} -.glyphicon-object-align-vertical:before { - content: "\e248"; -} -.glyphicon-object-align-right:before { - content: "\e249"; -} -.glyphicon-triangle-right:before { - content: "\e250"; -} -.glyphicon-triangle-left:before { - content: "\e251"; -} -.glyphicon-triangle-bottom:before { - content: "\e252"; -} -.glyphicon-triangle-top:before { - content: "\e253"; -} -.glyphicon-console:before { - content: "\e254"; -} -.glyphicon-superscript:before { - content: "\e255"; -} -.glyphicon-subscript:before { - content: "\e256"; -} -.glyphicon-menu-left:before { - content: "\e257"; -} -.glyphicon-menu-right:before { - content: "\e258"; -} -.glyphicon-menu-down:before { - content: "\e259"; -} -.glyphicon-menu-up:before { - content: "\e260"; -} -* { - -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: 10px; - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff; -} -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -a { - color: #337ab7; - text-decoration: none; -} -a:hover, -a:focus { - color: #23527c; - text-decoration: underline; -} -a:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -figure { - margin: 0; -} -img { - vertical-align: middle; -} -.img-responsive, -.thumbnail > img, -.thumbnail a > img, -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; -} -.img-rounded { - border-radius: 6px; -} -.img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; -} -.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; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} -[role="button"] { - cursor: pointer; -} -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: normal; - line-height: 1; - color: #777; -} -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: 300; - line-height: 1.4; -} -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} -small, -.small { - font-size: 85%; -} -mark, -.mark { - padding: .2em; - background-color: #fcf8e3; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -.text-justify { - text-align: justify; -} -.text-nowrap { - white-space: nowrap; -} -.text-lowercase { - text-transform: lowercase; -} -.text-uppercase { - text-transform: uppercase; -} -.text-capitalize { - text-transform: capitalize; -} -.text-muted { - color: #777; -} -.text-primary { - color: #337ab7; -} -a.text-primary:hover, -a.text-primary:focus { - color: #286090; -} -.text-success { - color: #3c763d; -} -a.text-success:hover, -a.text-success:focus { - color: #2b542c; -} -.text-info { - color: #31708f; -} -a.text-info:hover, -a.text-info:focus { - color: #245269; -} -.text-warning { - color: #8a6d3b; -} -a.text-warning:hover, -a.text-warning:focus { - color: #66512c; -} -.text-danger { - color: #a94442; -} -a.text-danger:hover, -a.text-danger:focus { - color: #843534; -} -.bg-primary { - color: #fff; - background-color: #337ab7; -} -a.bg-primary:hover, -a.bg-primary:focus { - background-color: #286090; -} -.bg-success { - background-color: #dff0d8; -} -a.bg-success:hover, -a.bg-success:focus { - background-color: #c1e2b3; -} -.bg-info { - background-color: #d9edf7; -} -a.bg-info:hover, -a.bg-info:focus { - background-color: #afd9ee; -} -.bg-warning { - background-color: #fcf8e3; -} -a.bg-warning:hover, -a.bg-warning:focus { - background-color: #f7ecb5; -} -.bg-danger { - background-color: #f2dede; -} -a.bg-danger:hover, -a.bg-danger:focus { - 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; - margin-left: -5px; - list-style: none; -} -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} -dl { - margin-top: 0; - margin-bottom: 20px; -} -dt, -dd { - line-height: 1.42857143; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; -} -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } -} -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #777; -} -.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.42857143; - color: #777; -} -blockquote footer:before, -blockquote small:before, -blockquote .small:before { - content: '\2014 \00A0'; -} -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0; -} -.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'; -} -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; -} -code, -kbd, -pre, -samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px; -} -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); -} -kbd kbd { - padding: 0; - font-size: 100%; - font-weight: bold; - -webkit-box-shadow: none; - box-shadow: none; -} -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - 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 { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -@media (min-width: 768px) { - .container { - width: 750px; - } -} -@media (min-width: 992px) { - .container { - width: 970px; - } -} -@media (min-width: 1200px) { - .container { - width: 1170px; - } -} -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -.row { - margin-right: -15px; - margin-left: -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-right: 15px; - padding-left: 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.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.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.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .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.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .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.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0; - } -} -table { - background-color: transparent; -} -caption { - padding-top: 8px; - padding-bottom: 8px; - color: #777; - text-align: left; -} -th { - text-align: left; -} -.table { - width: 100%; - max-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.42857143; - 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-of-type(odd) { - background-color: #f9f9f9; -} -.table-hover > tbody > tr:hover { - background-color: #f5f5f5; -} -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} -table td[class*="col-"], -table th[class*="col-"] { - position: static; - display: table-cell; - float: none; -} -.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:hover > .active, -.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:hover > .success, -.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:hover > .info, -.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:hover > .warning, -.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:hover > .danger, -.table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; -} -.table-responsive { - min-height: .01%; - overflow-x: auto; -} -@media screen and (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .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 { - min-width: 0; - padding: 0; - margin: 0; - border: 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; - max-width: 100%; - margin-bottom: 5px; - font-weight: bold; -} -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: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555; -} -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - 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, -webkit-box-shadow ease-in-out .15s; - -o-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; - opacity: 1; -} -.form-control:-ms-input-placeholder { - color: #999; -} -.form-control::-webkit-input-placeholder { - color: #999; -} -.form-control::-ms-expand { - background-color: transparent; - border: 0; -} -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - background-color: #eee; - opacity: 1; -} -.form-control[disabled], -fieldset[disabled] .form-control { - cursor: not-allowed; -} -textarea.form-control { - height: auto; -} -input[type="search"] { - -webkit-appearance: none; -} -@media screen and (-webkit-min-device-pixel-ratio: 0) { - input[type="date"].form-control, - input[type="time"].form-control, - input[type="datetime-local"].form-control, - input[type="month"].form-control { - line-height: 34px; - } - input[type="date"].input-sm, - input[type="time"].input-sm, - input[type="datetime-local"].input-sm, - input[type="month"].input-sm, - .input-group-sm input[type="date"], - .input-group-sm input[type="time"], - .input-group-sm input[type="datetime-local"], - .input-group-sm input[type="month"] { - line-height: 30px; - } - input[type="date"].input-lg, - input[type="time"].input-lg, - input[type="datetime-local"].input-lg, - input[type="month"].input-lg, - .input-group-lg input[type="date"], - .input-group-lg input[type="time"], - .input-group-lg input[type="datetime-local"], - .input-group-lg input[type="month"] { - line-height: 46px; - } -} -.form-group { - margin-bottom: 15px; -} -.radio, -.checkbox { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px; -} -.radio label, -.checkbox label { - min-height: 20px; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} -.radio-inline, -.checkbox-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"].disabled, -input[type="checkbox"].disabled, -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"] { - cursor: not-allowed; -} -.radio-inline.disabled, -.checkbox-inline.disabled, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} -.radio.disabled label, -.checkbox.disabled label, -fieldset[disabled] .radio label, -fieldset[disabled] .checkbox label { - cursor: not-allowed; -} -.form-control-static { - min-height: 34px; - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0; -} -.form-control-static.input-lg, -.form-control-static.input-sm { - padding-right: 0; - padding-left: 0; -} -.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; -} -.form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.form-group-sm select.form-control { - height: 30px; - line-height: 30px; -} -.form-group-sm textarea.form-control, -.form-group-sm select[multiple].form-control { - height: auto; -} -.form-group-sm .form-control-static { - height: 30px; - min-height: 32px; - padding: 6px 10px; - font-size: 12px; - line-height: 1.5; -} -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-lg { - height: 46px; - line-height: 46px; -} -textarea.input-lg, -select[multiple].input-lg { - height: auto; -} -.form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.form-group-lg select.form-control { - height: 46px; - line-height: 46px; -} -.form-group-lg textarea.form-control, -.form-group-lg select[multiple].form-control { - height: auto; -} -.form-group-lg .form-control-static { - height: 46px; - min-height: 38px; - padding: 11px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.has-feedback { - position: relative; -} -.has-feedback .form-control { - padding-right: 42.5px; -} -.form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; - pointer-events: none; -} -.input-lg + .form-control-feedback, -.input-group-lg + .form-control-feedback, -.form-group-lg .form-control + .form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px; -} -.input-sm + .form-control-feedback, -.input-group-sm + .form-control-feedback, -.form-group-sm .form-control + .form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px; -} -.has-success .help-block, -.has-success .control-label, -.has-success .radio, -.has-success .checkbox, -.has-success .radio-inline, -.has-success .checkbox-inline, -.has-success.radio label, -.has-success.checkbox label, -.has-success.radio-inline label, -.has-success.checkbox-inline label { - 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; - background-color: #dff0d8; - border-color: #3c763d; -} -.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, -.has-warning.radio label, -.has-warning.checkbox label, -.has-warning.radio-inline label, -.has-warning.checkbox-inline label { - 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; - background-color: #fcf8e3; - border-color: #8a6d3b; -} -.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, -.has-error.radio label, -.has-error.checkbox label, -.has-error.radio-inline label, -.has-error.checkbox-inline label { - 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; - background-color: #f2dede; - border-color: #a94442; -} -.has-error .form-control-feedback { - color: #a94442; -} -.has-feedback label ~ .form-control-feedback { - top: 25px; -} -.has-feedback label.sr-only ~ .form-control-feedback { - top: 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 .form-control-static { - display: inline-block; - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle; - } - .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn, - .form-inline .input-group .form-control { - width: auto; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .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; - vertical-align: middle; - } - .form-inline .radio label, - .form-inline .checkbox label { - padding-left: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } -} -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} -.form-horizontal .radio, -.form-horizontal .checkbox { - min-height: 27px; -} -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right; - } -} -.form-horizontal .has-feedback .form-control-feedback { - right: 15px; -} -@media (min-width: 768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 11px; - font-size: 18px; - } -} -@media (min-width: 768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px; - font-size: 12px; - } -} -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.btn:focus, -.btn:active:focus, -.btn.active:focus, -.btn.focus, -.btn:active.focus, -.btn.active.focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn:hover, -.btn:focus, -.btn.focus { - color: #333; - text-decoration: none; -} -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -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; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; -} -a.btn.disabled, -fieldset[disabled] a.btn { - pointer-events: none; -} -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; -} -.btn-default:focus, -.btn-default.focus { - color: #333; - background-color: #e6e6e6; - border-color: #8c8c8c; -} -.btn-default:hover { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active:hover, -.btn-default.active:hover, -.open > .dropdown-toggle.btn-default:hover, -.btn-default:active:focus, -.btn-default.active:focus, -.open > .dropdown-toggle.btn-default:focus, -.btn-default:active.focus, -.btn-default.active.focus, -.open > .dropdown-toggle.btn-default.focus { - color: #333; - background-color: #d4d4d4; - border-color: #8c8c8c; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - background-image: none; -} -.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.focus, -.btn-default[disabled].focus, -fieldset[disabled] .btn-default.focus { - background-color: #fff; - border-color: #ccc; -} -.btn-default .badge { - color: #fff; - background-color: #333; -} -.btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary:focus, -.btn-primary.focus { - color: #fff; - background-color: #286090; - border-color: #122b40; -} -.btn-primary:hover { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active:hover, -.btn-primary.active:hover, -.open > .dropdown-toggle.btn-primary:hover, -.btn-primary:active:focus, -.btn-primary.active:focus, -.open > .dropdown-toggle.btn-primary:focus, -.btn-primary:active.focus, -.btn-primary.active.focus, -.open > .dropdown-toggle.btn-primary.focus { - color: #fff; - background-color: #204d74; - border-color: #122b40; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - background-image: none; -} -.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.focus, -.btn-primary[disabled].focus, -fieldset[disabled] .btn-primary.focus { - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary .badge { - color: #337ab7; - background-color: #fff; -} -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success:focus, -.btn-success.focus { - color: #fff; - background-color: #449d44; - border-color: #255625; -} -.btn-success:hover { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active:hover, -.btn-success.active:hover, -.open > .dropdown-toggle.btn-success:hover, -.btn-success:active:focus, -.btn-success.active:focus, -.open > .dropdown-toggle.btn-success:focus, -.btn-success:active.focus, -.btn-success.active.focus, -.open > .dropdown-toggle.btn-success.focus { - color: #fff; - background-color: #398439; - border-color: #255625; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - background-image: none; -} -.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.focus, -.btn-success[disabled].focus, -fieldset[disabled] .btn-success.focus { - 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:focus, -.btn-info.focus { - color: #fff; - background-color: #31b0d5; - border-color: #1b6d85; -} -.btn-info:hover { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active:hover, -.btn-info.active:hover, -.open > .dropdown-toggle.btn-info:hover, -.btn-info:active:focus, -.btn-info.active:focus, -.open > .dropdown-toggle.btn-info:focus, -.btn-info:active.focus, -.btn-info.active.focus, -.open > .dropdown-toggle.btn-info.focus { - color: #fff; - background-color: #269abc; - border-color: #1b6d85; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - background-image: none; -} -.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.focus, -.btn-info[disabled].focus, -fieldset[disabled] .btn-info.focus { - 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:focus, -.btn-warning.focus { - color: #fff; - background-color: #ec971f; - border-color: #985f0d; -} -.btn-warning:hover { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active:hover, -.btn-warning.active:hover, -.open > .dropdown-toggle.btn-warning:hover, -.btn-warning:active:focus, -.btn-warning.active:focus, -.open > .dropdown-toggle.btn-warning:focus, -.btn-warning:active.focus, -.btn-warning.active.focus, -.open > .dropdown-toggle.btn-warning.focus { - color: #fff; - background-color: #d58512; - border-color: #985f0d; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - background-image: none; -} -.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.focus, -.btn-warning[disabled].focus, -fieldset[disabled] .btn-warning.focus { - 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:focus, -.btn-danger.focus { - color: #fff; - background-color: #c9302c; - border-color: #761c19; -} -.btn-danger:hover { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active:hover, -.btn-danger.active:hover, -.open > .dropdown-toggle.btn-danger:hover, -.btn-danger:active:focus, -.btn-danger.active:focus, -.open > .dropdown-toggle.btn-danger:focus, -.btn-danger:active.focus, -.btn-danger.active.focus, -.open > .dropdown-toggle.btn-danger.focus { - color: #fff; - background-color: #ac2925; - border-color: #761c19; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - background-image: none; -} -.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.focus, -.btn-danger[disabled].focus, -fieldset[disabled] .btn-danger.focus { - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger .badge { - color: #d9534f; - background-color: #fff; -} -.btn-link { - font-weight: normal; - color: #337ab7; - border-radius: 0; -} -.btn-link, -.btn-link:active, -.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: #23527c; - 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: #777; - text-decoration: none; -} -.btn-lg, -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.btn-sm, -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-xs, -.btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-block { - display: block; - width: 100%; -} -.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; - -o-transition: opacity .15s linear; - transition: opacity .15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - display: none; -} -.collapse.in { - display: block; -} -tr.collapse.in { - display: table-row; -} -tbody.collapse.in { - display: table-row-group; -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; - -webkit-transition-duration: .35s; - -o-transition-duration: .35s; - transition-duration: .35s; - -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility; -} -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-top: 4px solid \9; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} -.dropup, -.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; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - 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); -} -.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: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #777; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-menu-right { - right: 0; - left: auto; -} -.dropdown-menu-left { - right: auto; - left: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap; -} -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px dashed; - border-bottom: 4px solid \9; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } -} -.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 + .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, -.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-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-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:not(:last-child) > .btn:last-child, -.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 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-left-radius: 4px; - 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-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.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-left-radius: 0; - border-top-right-radius: 0; -} -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; -} -.btn-group-justified > .btn, -.btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; -} -.btn-group-justified > .btn-group .btn { - width: 100%; -} -.btn-group-justified > .btn-group .dropdown-menu { - left: auto; -} -[data-toggle="buttons"] > .btn input[type="radio"], -[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], -[data-toggle="buttons"] > .btn input[type="checkbox"], -[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; -} -.input-group { - position: relative; - display: table; - border-collapse: separate; -} -.input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; -} -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; -} -.input-group .form-control:focus { - z-index: 3; -} -.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.3333333; - 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: normal; - 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-top-right-radius: 0; - border-bottom-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-top-left-radius: 0; - border-bottom-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 { - z-index: 2; - margin-left: -1px; -} -.nav { - padding-left: 0; - margin-bottom: 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: #777; -} -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eee; - border-color: #337ab7; -} -.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.42857143; - 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; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} -.nav-tabs.nav-justified > li { - float: none; -} -.nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.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: #337ab7; -} -.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 { - margin-bottom: 5px; - text-align: center; -} -.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-left-radius: 0; - border-top-right-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 { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); -} -.navbar-collapse.in { - overflow-y: auto; -} -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - 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-right: 0; - padding-left: 0; - } -} -.navbar-fixed-top .navbar-collapse, -.navbar-fixed-bottom .navbar-collapse { - max-height: 340px; -} -@media (max-device-width: 480px) and (orientation: landscape) { - .navbar-fixed-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - max-height: 200px; - } -} -.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; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} -.navbar-brand > img { - display: block; -} -@media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } -} -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - 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; - -webkit-box-shadow: none; - 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-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -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); -} -@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 .form-control-static { - display: inline-block; - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle; - } - .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn, - .navbar-form .input-group .form-control { - width: auto; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .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; - vertical-align: middle; - } - .navbar-form .radio label, - .navbar-form .checkbox label { - padding-left: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } -} -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } - .navbar-form .form-group:last-child { - margin-bottom: 0; - } -} -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } -} -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - margin-bottom: 0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - 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-right: 15px; - margin-left: 15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - margin-right: -15px; - } - .navbar-right ~ .navbar-right { - 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 { - color: #555; - background-color: #e7e7e7; -} -@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-default .btn-link { - color: #777; -} -.navbar-default .btn-link:hover, -.navbar-default .btn-link:focus { - color: #333; -} -.navbar-default .btn-link[disabled]:hover, -fieldset[disabled] .navbar-default .btn-link:hover, -.navbar-default .btn-link[disabled]:focus, -fieldset[disabled] .navbar-default .btn-link:focus { - color: #ccc; -} -.navbar-inverse { - background-color: #222; - border-color: #080808; -} -.navbar-inverse .navbar-brand { - color: #9d9d9d; -} -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-text { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a { - color: #9d9d9d; -} -.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 { - color: #fff; - background-color: #080808; -} -@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: #9d9d9d; - } - .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: #9d9d9d; -} -.navbar-inverse .navbar-link:hover { - color: #fff; -} -.navbar-inverse .btn-link { - color: #9d9d9d; -} -.navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link:focus { - color: #fff; -} -.navbar-inverse .btn-link[disabled]:hover, -fieldset[disabled] .navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link[disabled]:focus, -fieldset[disabled] .navbar-inverse .btn-link:focus { - color: #444; -} -.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 { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; -} -.breadcrumb > .active { - color: #777; -} -.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; - margin-left: -1px; - line-height: 1.42857143; - color: #337ab7; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; -} -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - z-index: 2; - color: #23527c; - 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: 3; - color: #fff; - cursor: default; - background-color: #337ab7; - border-color: #337ab7; -} -.pagination > .disabled > span, -.pagination > .disabled > span:hover, -.pagination > .disabled > span:focus, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; -} -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; -} -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; -} -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} -.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: #777; - cursor: not-allowed; - background-color: #fff; -} -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} -a.label:hover, -a.label:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.label:empty { - display: none; -} -.btn .label { - position: relative; - top: -1px; -} -.label-default { - background-color: #777; -} -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #5e5e5e; -} -.label-primary { - background-color: #337ab7; -} -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #286090; -} -.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: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: middle; - background-color: #777; - border-radius: 10px; -} -.badge:empty { - display: none; -} -.btn .badge { - position: relative; - top: -1px; -} -.btn-xs .badge, -.btn-group-xs > .btn .badge { - top: 0; - padding: 1px 5px; -} -a.badge:hover, -a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #337ab7; - background-color: #fff; -} -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -} -.jumbotron { - padding-top: 30px; - padding-bottom: 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; -} -.jumbotron > hr { - border-top-color: #d5d5d5; -} -.container .jumbotron, -.container-fluid .jumbotron { - padding-right: 15px; - padding-left: 15px; - border-radius: 6px; -} -.jumbotron .container { - max-width: 100%; -} -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron, - .container-fluid .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: border .2s ease-in-out; - -o-transition: border .2s ease-in-out; - transition: border .2s ease-in-out; -} -.thumbnail > img, -.thumbnail a > img { - margin-right: auto; - margin-left: auto; -} -a.thumbnail:hover, -a.thumbnail:focus, -a.thumbnail.active { - border-color: #337ab7; -} -.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: bold; -} -.alert > p, -.alert > ul { - margin-bottom: 0; -} -.alert > p + p { - margin-top: 5px; -} -.alert-dismissable, -.alert-dismissible { - padding-right: 35px; -} -.alert-dismissable .close, -.alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-success hr { - border-top-color: #c9e2b3; -} -.alert-success .alert-link { - color: #2b542c; -} -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-info hr { - border-top-color: #a6e1ec; -} -.alert-info .alert-link { - color: #245269; -} -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.alert-warning hr { - border-top-color: #f7e1b5; -} -.alert-warning .alert-link { - color: #66512c; -} -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.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; - } -} -@-o-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 { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - 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: #337ab7; - -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; - -o-transition: width .6s ease; - transition: width .6s ease; -} -.progress-striped .progress-bar, -.progress-bar-striped { - 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: -o-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); - -webkit-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .progress-bar, -.progress-bar.active { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-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: -o-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: -o-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: -o-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: -o-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 { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media-body { - width: 10000px; -} -.media-object { - display: block; -} -.media-object.img-thumbnail { - max-width: none; -} -.media-right, -.media > .pull-right { - padding-left: 10px; -} -.media-left, -.media > .pull-left { - padding-right: 10px; -} -.media-left, -.media-right, -.media-body { - display: table-cell; - vertical-align: top; -} -.media-middle { - vertical-align: middle; -} -.media-bottom { - vertical-align: bottom; -} -.media-heading { - margin-top: 0; - margin-bottom: 5px; -} -.media-list { - padding-left: 0; - list-style: none; -} -.list-group { - padding-left: 0; - margin-bottom: 20px; -} -.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-left-radius: 4px; - border-top-right-radius: 4px; -} -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -a.list-group-item, -button.list-group-item { - color: #555; -} -a.list-group-item .list-group-item-heading, -button.list-group-item .list-group-item-heading { - color: #333; -} -a.list-group-item:hover, -button.list-group-item:hover, -a.list-group-item:focus, -button.list-group-item:focus { - color: #555; - text-decoration: none; - background-color: #f5f5f5; -} -button.list-group-item { - width: 100%; - text-align: left; -} -.list-group-item.disabled, -.list-group-item.disabled:hover, -.list-group-item.disabled:focus { - color: #777; - cursor: not-allowed; - background-color: #eee; -} -.list-group-item.disabled .list-group-item-heading, -.list-group-item.disabled:hover .list-group-item-heading, -.list-group-item.disabled:focus .list-group-item-heading { - color: inherit; -} -.list-group-item.disabled .list-group-item-text, -.list-group-item.disabled:hover .list-group-item-text, -.list-group-item.disabled:focus .list-group-item-text { - color: #777; -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading, -.list-group-item.active .list-group-item-heading > small, -.list-group-item.active:hover .list-group-item-heading > small, -.list-group-item.active:focus .list-group-item-heading > small, -.list-group-item.active .list-group-item-heading > .small, -.list-group-item.active:hover .list-group-item-heading > .small, -.list-group-item.active:focus .list-group-item-heading > .small { - color: inherit; -} -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #c7ddef; -} -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8; -} -a.list-group-item-success, -button.list-group-item-success { - color: #3c763d; -} -a.list-group-item-success .list-group-item-heading, -button.list-group-item-success .list-group-item-heading { - color: inherit; -} -a.list-group-item-success:hover, -button.list-group-item-success:hover, -a.list-group-item-success:focus, -button.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; -} -a.list-group-item-success.active, -button.list-group-item-success.active, -a.list-group-item-success.active:hover, -button.list-group-item-success.active:hover, -a.list-group-item-success.active:focus, -button.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, -button.list-group-item-info { - color: #31708f; -} -a.list-group-item-info .list-group-item-heading, -button.list-group-item-info .list-group-item-heading { - color: inherit; -} -a.list-group-item-info:hover, -button.list-group-item-info:hover, -a.list-group-item-info:focus, -button.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; -} -a.list-group-item-info.active, -button.list-group-item-info.active, -a.list-group-item-info.active:hover, -button.list-group-item-info.active:hover, -a.list-group-item-info.active:focus, -button.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, -button.list-group-item-warning { - color: #8a6d3b; -} -a.list-group-item-warning .list-group-item-heading, -button.list-group-item-warning .list-group-item-heading { - color: inherit; -} -a.list-group-item-warning:hover, -button.list-group-item-warning:hover, -a.list-group-item-warning:focus, -button.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; -} -a.list-group-item-warning.active, -button.list-group-item-warning.active, -a.list-group-item-warning.active:hover, -button.list-group-item-warning.active:hover, -a.list-group-item-warning.active:focus, -button.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, -button.list-group-item-danger { - color: #a94442; -} -a.list-group-item-danger .list-group-item-heading, -button.list-group-item-danger .list-group-item-heading { - color: inherit; -} -a.list-group-item-danger:hover, -button.list-group-item-danger:hover, -a.list-group-item-danger:focus, -button.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; -} -a.list-group-item-danger.active, -button.list-group-item-danger.active, -a.list-group-item-danger.active:hover, -button.list-group-item-danger.active:hover, -a.list-group-item-danger.active:focus, -button.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-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-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, -.panel-title > small, -.panel-title > .small, -.panel-title > small > a, -.panel-title > .small > 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 > .list-group, -.panel > .panel-collapse > .list-group { - margin-bottom: 0; -} -.panel > .list-group .list-group-item, -.panel > .panel-collapse > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; -} -.panel > .list-group:first-child .list-group-item:first-child, -.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .list-group:last-child .list-group-item:last-child, -.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} -.list-group + .panel-footer { - border-top-width: 0; -} -.panel > .table, -.panel > .table-responsive > .table, -.panel > .panel-collapse > .table { - margin-bottom: 0; -} -.panel > .table caption, -.panel > .table-responsive > .table caption, -.panel > .panel-collapse > .table caption { - padding-right: 15px; - padding-left: 15px; -} -.panel > .table:first-child, -.panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.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, -.panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-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, -.panel > .table + .panel-body, -.panel > .table-responsive + .panel-body { - 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 > 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 > 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 { - border-bottom: 0; -} -.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, -.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 { - border-bottom: 0; -} -.panel > .table-responsive { - margin-bottom: 0; - border: 0; -} -.panel-group { - margin-bottom: 20px; -} -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px; -} -.panel-group .panel + .panel { - margin-top: 5px; -} -.panel-group .panel-heading { - border-bottom: 0; -} -.panel-group .panel-heading + .panel-collapse > .panel-body, -.panel-group .panel-heading + .panel-collapse > .list-group { - 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-heading .badge { - color: #f5f5f5; - background-color: #333; -} -.panel-default > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ddd; -} -.panel-primary { - border-color: #337ab7; -} -.panel-primary > .panel-heading { - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.panel-primary > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #337ab7; -} -.panel-primary > .panel-heading .badge { - color: #337ab7; - background-color: #fff; -} -.panel-primary > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #337ab7; -} -.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-heading .badge { - color: #dff0d8; - background-color: #3c763d; -} -.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-heading .badge { - color: #d9edf7; - background-color: #31708f; -} -.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-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b; -} -.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-heading .badge { - color: #f2dede; - background-color: #a94442; -} -.panel-danger > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ebccd1; -} -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden; -} -.embed-responsive .embed-responsive-item, -.embed-responsive iframe, -.embed-responsive embed, -.embed-responsive object, -.embed-responsive video { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; -} -.embed-responsive-16by9 { - padding-bottom: 56.25%; -} -.embed-responsive-4by3 { - padding-bottom: 75%; -} -.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: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: .2; -} -.close:hover, -.close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; -} -button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; -} -.modal-open { - overflow: hidden; -} -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0; -} -.modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%); -} -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0); -} -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto; -} -.modal-dialog { - position: relative; - width: auto; - margin: 10px; -} -.modal-content { - position: relative; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; -} -.modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; -} -.modal-backdrop.in { - filter: alpha(opacity=50); - opacity: .5; -} -.modal-header { - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} -.modal-header .close { - margin-top: -2px; -} -.modal-title { - margin: 0; - line-height: 1.42857143; -} -.modal-body { - position: relative; - padding: 15px; -} -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll; -} -@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; - } -} -@media (min-width: 992px) { - .modal-lg { - width: 900px; - } -} -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - filter: alpha(opacity=0); - opacity: 0; - - line-break: auto; -} -.tooltip.in { - filter: alpha(opacity=90); - opacity: .9; -} -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - 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 { - right: 5px; - bottom: 0; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -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; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - background-color: #fff; - -webkit-background-clip: padding-box; - 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); - - line-break: auto; -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - 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 { - content: ""; - border-width: 10px; -} -.popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0; -} -.popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; -} -.popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0; -} -.popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; -} -.popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); -} -.popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - 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 { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; -} -.carousel { - position: relative; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - line-height: 1; -} -@media all and (transform-3d), (-webkit-transform-3d) { - .carousel-inner > .item { - -webkit-transition: -webkit-transform .6s ease-in-out; - -o-transition: -o-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-perspective: 1000px; - perspective: 1000px; - } - .carousel-inner > .item.next, - .carousel-inner > .item.active.right { - left: 0; - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); - } - .carousel-inner > .item.prev, - .carousel-inner > .item.active.left { - left: 0; - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); - } - .carousel-inner > .item.next.left, - .carousel-inner > .item.prev.right, - .carousel-inner > .item.active { - left: 0; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} -.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; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - background-color: rgba(0, 0, 0, 0); - filter: alpha(opacity=50); - opacity: .5; -} -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control:hover, -.carousel-control:focus { - color: #fff; - text-decoration: none; - filter: alpha(opacity=90); - outline: 0; - opacity: .9; -} -.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; - margin-top: -10px; -} -.carousel-control .icon-prev, -.carousel-control .glyphicon-chevron-left { - left: 50%; - margin-left: -10px; -} -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-right { - right: 50%; - margin-right: -10px; -} -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - font-family: serif; - line-height: 1; -} -.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%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; -} -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; -} -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - 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 .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -10px; - font-size: 30px; - } - .carousel-control .glyphicon-chevron-left, - .carousel-control .icon-prev { - margin-left: -10px; - } - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next { - margin-right: -10px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after, -.dl-horizontal dd:before, -.dl-horizontal dd: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-header:before, -.modal-header:after, -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} -.clearfix:after, -.dl-horizontal dd: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-header:after, -.modal-footer:after { - clear: both; -} -.center-block { - display: block; - margin-right: auto; - margin-left: 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; -} -.affix { - position: fixed; -} -@-ms-viewport { - width: device-width; -} -.visible-xs, -.visible-sm, -.visible-md, -.visible-lg { - display: none !important; -} -.visible-xs-block, -.visible-xs-inline, -.visible-xs-inline-block, -.visible-sm-block, -.visible-sm-inline, -.visible-sm-inline-block, -.visible-md-block, -.visible-md-inline, -.visible-md-inline-block, -.visible-lg-block, -.visible-lg-inline, -.visible-lg-inline-block { - display: none !important; -} -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table !important; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} -@media (max-width: 767px) { - .visible-xs-block { - display: block !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline { - display: inline !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline-block { - display: inline-block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table !important; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-block { - display: block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline { - display: inline !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline-block { - display: inline-block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table !important; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-block { - display: block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline { - display: inline !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline-block { - display: inline-block !important; - } -} -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table !important; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-lg-block { - display: block !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline { - display: inline !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline-block { - display: inline-block !important; - } -} -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } -} -.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table !important; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } -} -.visible-print-block { - display: none !important; -} -@media print { - .visible-print-block { - display: block !important; - } -} -.visible-print-inline { - display: none !important; -} -@media print { - .visible-print-inline { - display: inline !important; - } -} -.visible-print-inline-block { - display: none !important; -} -@media print { - .visible-print-inline-block { - display: inline-block !important; - } -} -@media print { - .hidden-print { - display: none !important; - } -} -/*# sourceMappingURL=bootstrap.css.map */ diff --git a/hal-core/resources/web/css/lib/bootstrap.min.css b/hal-core/resources/web/css/lib/bootstrap.min.css deleted file mode 100644 index 2b8fc88d..00000000 --- a/hal-core/resources/web/css/lib/bootstrap.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,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-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}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{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;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-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!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:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@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.woff2) format('woff2'),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:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.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"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.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;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.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,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,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,.h5,.h6,h4,h5,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:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.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 ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;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{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.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-md-1,.col-md-10,.col-md-11,.col-md-12,.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-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.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-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;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>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border: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;max-width:100%;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=checkbox],input[type=radio]{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=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;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,-webkit-box-shadow ease-in-out .15s;-o-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;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.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}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{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;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{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;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{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;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top: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 .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-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;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{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.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{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.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{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.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{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;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;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)}.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.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.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,.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-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-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:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left: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-left-radius:4px;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-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.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-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.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.3333333;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}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.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}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn: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=checkbox],.input-group-addon input[type=radio]{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-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-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:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-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:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{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{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.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.42857143;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:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.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:focus,.nav-tabs.nav-justified>.active>a:hover{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:focus,.nav-tabs.nav-justified>.active>a:hover{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:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.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{margin-bottom:5px;text-align:center}.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:focus,.nav-tabs-justified>.active>a:hover{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:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-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{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;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-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{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-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{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;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;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;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{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-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-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)}@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 .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;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-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{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:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{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:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{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:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@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:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.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{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.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;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.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:focus,.pager li>a:hover{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:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.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}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom: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}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.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,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.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}}@-o-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{height:20px;margin-bottom:20px;overflow:hidden;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:#337ab7;-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;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.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:-o-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);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-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:-o-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:-o-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:-o-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:-o-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{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.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-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{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-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>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>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.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 th:first-child,.panel>.table-responsive:first-child>.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 th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.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 th:last-child,.panel>.table-responsive:first-child>.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 th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.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 th:first-child,.panel>.table-responsive:last-child>.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 th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.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 th:last-child,.panel>.table-responsive:last-child>.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 th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.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,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.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-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.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-heading .badge{color:#dff0d8;background-color:#3c763d}.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-heading .badge{color:#d9edf7;background-color:#31708f}.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-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.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-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.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;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@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}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;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{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-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;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;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);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;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{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";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{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.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;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.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%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;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 .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left: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}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} -/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/hal-core/resources/web/css/lib/c3.css b/hal-core/resources/web/css/lib/c3.css deleted file mode 100644 index fda42427..00000000 --- a/hal-core/resources/web/css/lib/c3.css +++ /dev/null @@ -1,167 +0,0 @@ -/*-- Chart --*/ -.c3 svg { - font: 10px sans-serif; - -webkit-tap-highlight-color: transparent; } - -.c3 path, .c3 line { - fill: none; - stroke: #000; } - -.c3 text { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; } - -.c3-legend-item-tile, -.c3-xgrid-focus, -.c3-ygrid, -.c3-event-rect, -.c3-bars path { - shape-rendering: crispEdges; } - -.c3-chart-arc path { - stroke: #fff; } - -.c3-chart-arc text { - fill: #fff; - font-size: 13px; } - -/*-- Axis --*/ -/*-- Grid --*/ -.c3-grid line { - stroke: #aaa; } - -.c3-grid text { - fill: #aaa; } - -.c3-xgrid, .c3-ygrid { - stroke-dasharray: 3 3; } - -/*-- Text on Chart --*/ -.c3-text.c3-empty { - fill: #808080; - font-size: 2em; } - -/*-- Line --*/ -.c3-line { - stroke-width: 1px; } - -/*-- Point --*/ -.c3-circle._expanded_ { - stroke-width: 1px; - stroke: white; } - -.c3-selected-circle { - fill: white; - stroke-width: 2px; } - -/*-- Bar --*/ -.c3-bar { - stroke-width: 0; } - -.c3-bar._expanded_ { - fill-opacity: 0.75; } - -/*-- Focus --*/ -.c3-target.c3-focused { - opacity: 1; } - -.c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step { - stroke-width: 2px; } - -.c3-target.c3-defocused { - opacity: 0.3 !important; } - -/*-- Region --*/ -.c3-region { - fill: steelblue; - fill-opacity: .1; } - -/*-- Brush --*/ -.c3-brush .extent { - fill-opacity: .1; } - -/*-- Select - Drag --*/ -/*-- Legend --*/ -.c3-legend-item { - font-size: 12px; } - -.c3-legend-item-hidden { - opacity: 0.15; } - -.c3-legend-background { - opacity: 0.75; - fill: white; - stroke: lightgray; - stroke-width: 1; } - -/*-- Title --*/ -.c3-title { - font: 14px sans-serif; } - -/*-- Tooltip --*/ -.c3-tooltip-container { - z-index: 10; } - -.c3-tooltip { - border-collapse: collapse; - border-spacing: 0; - background-color: #fff; - empty-cells: show; - -webkit-box-shadow: 7px 7px 12px -9px #777777; - -moz-box-shadow: 7px 7px 12px -9px #777777; - box-shadow: 7px 7px 12px -9px #777777; - opacity: 0.9; } - -.c3-tooltip tr { - border: 1px solid #CCC; } - -.c3-tooltip th { - background-color: #aaa; - font-size: 14px; - padding: 2px 5px; - text-align: left; - color: #FFF; } - -.c3-tooltip td { - font-size: 13px; - padding: 3px 6px; - background-color: #fff; - border-left: 1px dotted #999; } - -.c3-tooltip td > span { - display: inline-block; - width: 10px; - height: 10px; - margin-right: 6px; } - -.c3-tooltip td.value { - text-align: right; } - -/*-- Area --*/ -.c3-area { - stroke-width: 0; - opacity: 0.2; } - -/*-- Arc --*/ -.c3-chart-arcs-title { - dominant-baseline: middle; - font-size: 1.3em; } - -.c3-chart-arcs .c3-chart-arcs-background { - fill: #e0e0e0; - stroke: none; } - -.c3-chart-arcs .c3-chart-arcs-gauge-unit { - fill: #000; - font-size: 16px; } - -.c3-chart-arcs .c3-chart-arcs-gauge-max { - fill: #777; } - -.c3-chart-arcs .c3-chart-arcs-gauge-min { - fill: #777; } - -.c3-chart-arc .c3-gauge-value { - fill: #000; - /* font-size: 28px !important;*/ } diff --git a/hal-core/resources/web/css/lib/c3.min.css b/hal-core/resources/web/css/lib/c3.min.css deleted file mode 100644 index 1e20d5b1..00000000 --- a/hal-core/resources/web/css/lib/c3.min.css +++ /dev/null @@ -1 +0,0 @@ -.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000} \ No newline at end of file diff --git a/hal-core/resources/web/css/lib/jquery.filer.css b/hal-core/resources/web/css/lib/jquery.filer.css deleted file mode 100644 index ead852a6..00000000 --- a/hal-core/resources/web/css/lib/jquery.filer.css +++ /dev/null @@ -1,438 +0,0 @@ -/*! - * CSS jQuery.filer - * Copyright (c) 2015 CreativeDream - * Version: 1.0.5 (19-Nov-2015) -*/ -/*@import url('../assets/fonts/jquery.filer-icons/jquery-filer.css');*/ - -/*------------------------- - Basic configurations --------------------------*/ -.jFiler * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.jFiler { - font-family: sans-serif; - font-size: 14px; - color: #494949; -} - -/* Helpers */ -.jFiler ul.list-inline li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} - -.jFiler .pull-left { - float: left; -} - -.jFiler .pull-right { - float: right; -} - -/* File Icons */ -span.jFiler-icon-file { - position: relative; - width: 57px; - height: 70px; - display: inline-block; - line-height: 70px; - text-align: center; - border-radius: 3px; - color: #fff; - font-family: sans-serif; - font-size: 13px; - font-weight: bold; - overflow: hidden; - box-shadow: 42px -55px 0 0 #A4A7AC inset; -} - -span.jFiler-icon-file:after { - position: absolute; - top: -1px; - right: -1px; - display: inline-block; - content: ''; - border-style: solid; - border-width: 16px 0 0 16px; - border-color: transparent transparent transparent #DADDE1; -} - -span.jFiler-icon-file i[class*="icon-jfi-"] { - font-size: 24px; -} - -span.jFiler-icon-file.f-image { - box-shadow: 42px -55px 0 0 #e15955 inset; -} - -span.jFiler-icon-file.f-image:after { - border-left-color: #c6393f; -} - -span.jFiler-icon-file.f-video { - box-shadow: 42px -55px 0 0 #4183d7 inset; -} - -span.jFiler-icon-file.f-video:after { - border-left-color: #446cb3; -} - -span.jFiler-icon-file.f-audio { - box-shadow: 42px -55px 0 0 #5bab6e inset; -} - -span.jFiler-icon-file.f-audio:after { - border-left-color: #448353; -} - - -/* Progress Bar */ -.jFiler-jProgressBar { - height: 8px; - background: #f1f1f1; - margin-top: 3px; - margin-bottom: 0; - overflow: hidden; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.jFiler-jProgressBar .bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - color: #ffffff; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #50A1E9; - box-sizing: border-box; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-transition: width 0.3s ease; - -moz-transition: width 0.3s ease; - -o-transition: width 0.3s ease; - transition: width 0.3s ease; -} - -.jFiler-jProgressBar .bar.dark { - background-color: #555; -} - -.jFiler-jProgressBar .bar.blue { - background-color: #428bca; -} - -.jFiler-jProgressBar .bar.green { - background-color: #5cb85c; -} - -.jFiler-jProgressBar .bar.orange { - background-color: #f7a923; -} - -.jFiler-jProgressBar .bar.red { - background-color: #d9534f; -} - -/* Thumbs */ -.jFiler-row:after, -.jFiler-item:after { - display: table; - line-height: 0; - content: ""; - clear: both; -} - -.jFiler-items ul { - margin: 0; - padding: 0; - list-style: none; -} - -/*------------------------- - Default Theme --------------------------*/ -.jFiler-theme-default .jFiler-input { - position: relative; - display: block; - width: 400px; - height: 35px; - margin: 0 0 15px 0; - background: #fefefe; - border: 1px solid #cecece; - font-size: 12px; - font-family: sans-serif; - color: #888; - border-radius: 4px; - cursor: pointer; - overflow: hidden; - -webkit-box-shadow: rgba(0,0,0,.25) 0 4px 5px -5px inset; - -moz-box-shadow: rgba(0,0,0,.25) 0 4px 5px -5px inset; - box-shadow: rgba(0,0,0,.25) 0 4px 5px -5px inset; -} - -.jFiler-theme-default .jFiler-input.focused { - outline: none; - -webkit-box-shadow: 0 0 7px rgba(0,0,0,0.1); - -moz-box-shadow: 0 0 7px rgba(0,0,0,0.1); - box-shadow: 0 0 7px rgba(0,0,0,0.1); -} - -.jFiler-theme-default .jFiler.dragged .jFiler-input { - border: 1px dashed #aaaaaa; - background: #f9f9f9; -} - -.jFiler-theme-default .jFiler.dragged .jFiler-input:hover { - background: #FFF8D0; -} - -.jFiler-theme-default .jFiler.dragged .jFiler-input * { - pointer-events: none; -} - -.jFiler-theme-default .jFiler.dragged .jFiler-input .jFiler-input-caption { - width: 100%; - text-align: center; -} - -.jFiler-theme-default .jFiler.dragged .jFiler-input .jFiler-input-button { - display: none; -} - -.jFiler-theme-default .jFiler-input-caption { - display: block; - float: left; - height: 100%; - padding-top: 8px; - padding-left: 10px; - text-overflow: ellipsis; - overflow: hidden; -} - -.jFiler-theme-default .jFiler-input-button { - display: block; - float: right; - height: 100%; - padding-top: 8px; - padding-left: 15px; - padding-right: 15px; - border-left: 1px solid #ccc; - color: #666666; - text-align: center; - background-color: #fefefe; - background-image: -webkit-gradient(linear,0 0,0 100%,from(#fefefe),to(#f1f1f1)); - background-image: -webkit-linear-gradient(top,#fefefe,#f1f1f1); - background-image: -o-linear-gradient(top,#fefefe,#f1f1f1); - background-image: linear-gradient(to bottom,#fefefe,#f1f1f1); - background-image: -moz-linear-gradient(top,#fefefe,#f1f1f1); - -webkit-transition: all .1s ease-out; - -moz-transition: all .1s ease-out; - -o-transition: all .1s ease-out; - transition: all .1s ease-out; -} - -.jFiler-theme-default .jFiler-input-button:hover { - -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.07); - -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.07); - box-shadow: inset 0 0 10px rgba(0,0,0,0.07); -} - -.jFiler-theme-default .jFiler-input-button:active { - background-image: -webkit-gradient(linear,0 0,0 100%,from(#f1f1f1),to(#fefefe)); - background-image: -webkit-linear-gradient(top,#f1f1f1,#fefefe); - background-image: -o-linear-gradient(top,#f1f1f1,#fefefe); - background-image: linear-gradient(to bottom,#f1f1f1,#fefefe); - background-image: -moz-linear-gradient(top,#f1f1f1,#fefefe); -} - -/*------------------------- - Thumbnails --------------------------*/ -.jFiler-items-default .jFiler-items { - -} - -.jFiler-items-default .jFiler-item { - position: relative; - padding: 16px; - margin-bottom: 16px; - background: #f7f7f7; - color: #4d4d4c; -} - - -.jFiler-items-default .jFiler-item .jFiler-item-icon { - font-size: 32px; - color: #f5871f; - - margin-right: 15px; - margin-top: -3px; -} - -.jFiler-items-default .jFiler-item .jFiler-item-title { - font-weight: bold; -} - -.jFiler-items-default .jFiler-item .jFiler-item-others { - font-size: 12px; - color: #777; - margin-left: -5px; - margin-right: -5px; -} - -.jFiler-items-default .jFiler-item .jFiler-item-others span { - padding-left: 5px; - padding-right: 5px; -} - -.jFiler-items-default .jFiler-item-assets { - position: absolute; - display: block; - right: 16px; - top: 50%; - margin-top: -10px; -} - -.jFiler-items-default .jFiler-item-assets a { - padding: 8px 9px 8px 12px; - cursor: pointer; - background: #fafafa; - color: #777; - border-radius: 4px; - border: 1px solid #e3e3e3 -} - -.jFiler-items-default .jFiler-item-assets .jFiler-item-trash-action:hover, -.jFiler-items-default .jFiler-item-assets .jFiler-item-trash-action:active { - color: #d9534f; -} - -.jFiler-items-default .jFiler-item-assets .jFiler-item-trash-action:active { - background: transparent; -} - -/* Thumbnails: Grid */ -.jFiler-items-grid .jFiler-item { - float: left; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container { - position: relative; - margin: 0 20px 30px 0; - padding: 10px; - border: 1px solid #e1e1e1; - border-radius: 3px; - background: #fff; - -webkit-box-shadow: 0px 0px 3px rgba(0,0,0,0.06); - -moz-box-shadow: 0px 0px 3px rgba(0,0,0,0.06); - box-shadow: 0px 0px 3px rgba(0,0,0,0.06); -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-thumb { - position: relative; - width: 160px; - height: 115px; - min-height: 115px; - border: 1px solid #e1e1e1; - overflow: hidden; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-thumb .jFiler-item-thumb-image { - width: 100%; - height: 100%; - text-align: center; -} - -.jFiler-item .jFiler-item-container .jFiler-item-thumb img { - max-width: none; - max-height: 100%; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-thumb span.jFiler-icon-file { - margin-top: 20px; -} - -.jFiler-items-grid .jFiler-item-thumb-image.fi-loading { - background: url('data:image/gif;base64,R0lGODlhIwAjAMQAAP////f39+/v7+bm5t7e3tbW1s7OzsXFxb29vbW1ta2traWlpZycnJSUlIyMjISEhHt7e3Nzc2tra2NjY1paWlJSUkpKSkJCQjo6OjExMSkpKRkZGRAQEAAAAP///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFBAAeACwAAAAAIwAjAAAF5CAgjmRpnmiqrmzrvnAsz3Rto4Fwm4EYLIweQHcTKAiAQOPRI0QKRcYiEGA4qI8K9HZoGAIOSOBgCdIGBeLCMUgoBJSJjsBAxAiKRSFAQBCVBwMKGRsNQi8DBwsJhyQVGxMKjTCJk0kPjDI5AlQqBAcICFstBQqmmScFGh0dHBaWKAIEBQQDKQEKDxEQCTMBA5Y/o5oDoZYCHB1PMgIHCQacwCPACRStDTEDBrYABQg5wAgGIg4YYjQCogEGB3wI3J2+oD0G42PfN2Pc7D2JRDb/+In4t8MHwYIIEypcyLChQ4YhAAAh+QQFBAAeACwIAAgAEwATAAAFlqAnjiKSjAFJBscgLos4NIQ6JggAKLHXSDWbp6CoLRgeg0ShGwkIKQ9iITggPJFHaqA4eAYIRK0a9SwK0spl0TQkvEIJJnIlCdDCRk4lEJIGBgcHRn4jBBkciROFKgkNDg51jCJBJJU2ARocD4xNAQsGCBMcGz2FAxwZKQwVDYVwEhwOI02MAxsceJMeOgwaJ7skCX0jIQAh+QQFBAAeACwAAAAAAQABAAAFA6AXAgAh+QQFBAAeACwAAAAAAQABAAAFA6AXAgAh+QQFBAAeACwJAAcAEgAVAAAFjqAnjmJAnihgHChqCACAJKMyoMHBeggSJ40baoC4zTwFB6IlOiwLhkCDMUIYUAUSgiA4RCZLAXPkoDQOsfFosVNjDYaBQiRmWjaaDMTdXDAYbWMJQnwiGBoOBEwmIwVeGhhzKAJ+BBsXIgoSVCcEAxkbAw8enEwAARkaYqluAqliChlLY64aQrNjAT2MKCEAIfkEBQQAHgAsBwAIABQAFAAABZqgJ45jUQBkqorGgQqIsKqteCjyTLbAsBg6UoBA8CgSIoGhGGQNAoXG4zAaNBcPxalJQhS4KwGhUCQgRYHZQGKxVBpgD8CQUCiAYEQTpZpcGFYrBgw5HgkEBg4XFHoqFx10CwMZFCIIDwl8IwscFAQXGR4NGQo6BBocRRUYHgIWGEwqBxoPHgEWoYYXVCsBCTIBqzkHaVwHvCshACH5BAUEAB4ALAAAAAABAAEAAAUDoBcCACH5BAUEAB4ALAcACAAVABQAAAWaoCeOpDECZKqKgRcY7bqanoHI6+EKSIHjCJ2oMPidCgIPQbHwGUkIBoLwJAEM1OpqQBgkC0yjwBGRRBQokfdXOASzo0MjqTrQUwQIpwM/QSYJKQoaHRUKHgtQSgwTEUIeDRcPSRQcHgiBFREiB1IkdAkaEgMUGAILFoE4AxkaRRIVLRIURTIGGQ0iExWcEzQyBzGwI05PV78rIQAh+QQFBAAeACwAAAAAAQABAAAFA6AXAgAh+QQFBAAeACwHAAgAFAAUAAAFlaAnjmRBnmgqCip6kEGbDnJqvmJAsLVIDwgEoTc6JAy0k05VSIoKiSgipgoIaIFKZ8tBVBeNBgORkEwkDt6sYECSBosUwJRybDiqxuOgTmTwCAUKIwAHAwMJDw10CxUNMRIaBQcIAmhPCgYjVAcZDx4REx5lOCoWGCIPER4Bqi0FFwwiEBIxBg9DKpqpEVS5PQUFACohACH5BAUEAB4ALAAAAAABAAEAAAUDoBcCACH5BAUEAB4ALAcACAAUABQAAAWRoCeOpEGeaCoGKmqOQlvKXgId4usR6DA+HA6kQDsxMB0Nr0hSTHxFAgJxIABogpiEI9rgVAiF2ICARCANVovAjsESKoKaNGBkMqrEojA/WDYSHgMIJAVZBwsKSwoSCyIOFx4FJg4LVwQHRCgVDQIOEAEHDi9XJwISFAIADA4iDJ1xEwoiDa2SDFA0rCO5NGwtIQAh+QQFBAAeACwAAAAAAQABAAAFA6AXAgAh+QQFBAAeACwHAAgAEwAUAAAFj6AnisNonqeBLWg7GpwmtAENcc8s6ifyGKJMp1DyIFqNjecxUEiKLpGi4slATcBW4hkdDQ6HbHd048TELtah8XCwxqjAsXXdKSyWuuiAILwmGBBABzUiBDUFCQglCBAJIgsTBAQFAQpzAwZ1BREsCwweBQt+Lg8QNQpvCAqFJwMQc6mGjy6kHrI7cB4DeiIhACH5BAUEAB4ALAAAAAABAAEAAAUDoBcCACH5BAUEAB4ALAcABwASABUAAAWXoCeOI0GQaBpUl5CSRZV4QrYN71hoWBBkGpdISAI4No2BhoNLHRijy8YQmQwOpJMC2BAgIh5fgJZKSDYWYg4FWZMMhkLT7XHYeAW6wrBgLGZ0KQZjgR4IEhFqJIAeBQ8UDQUCeSNzIwcNCCIJDwMDJwgGawSZAQgzBAiWIwELDSIHmh6xOQyiAKciV4oeAHO0IwB0ArweIQAh+QQFBAAeACwAAAAAAQABAAAFA6AXAgAh+QQFBAAeACwHAAcAEAAVAAAFjKAnjuMwkKgnjFJVosSEeMGVrcc1j8TlehVMIIDh7EaMzMKDuTE4k4DHsCiIKJnCI0LYcE6ehMWyPDxGgshyZL5MUqID6uCAowsEwsouWlTGFAR8HgUJCglHgyNWigF0dXYzBAwPCoJgcAUKBnELAgKYcAObHgdyfIYiBQcAdgIJjAanrq0AsoojQyghACH5BAUEAB4ALAAAAAABAAEAAAUDoBcCACH5BAUEAB4ALAcACAAUABQAAAWYoCeKwQhF5aiqA3SIlDVW7yoOlCRKlVhtNZtHYUkIKBfPYoNaFRADUUTWeAwyGYHHAFmIDhIJImBorBIFB6cDSZUnEGEA08k0UiPDQrsSTB58HgEDhEIqAHgIERESVoY2BAcIBwaPlh5Rl04KCnhnKwMJDFCelgMIBAAeT3hBNqoeAggFIgiaX7ZblZoBB5lbqoG3wzbCKyEAIfkEBQQAHgAsBwAHABUAEwAABZygJ46jIJBoSjZPqa6GGEmBZ0zx60Gt90QiSSb3QkgOHskkkMj0UAOkyCEhLBiey2X0SIwMLKRVAPAEHggCY8N5egiKB6OGAmwtC1UhQScFIgt9JAKCKQUICQkxBw2NCycqBhsdlBgBAwUGBgRlKgMPExMSgSSdKmQvBAgIOqwoAgeKkDopBgMiMbOutCgGSLe8IlIeSKbBI1LAKCEAIfkEBQQAHgAsAAAAAAEAAQAABQOgFwIAIfkEBQQAHgAsAAAAAAEAAQAABQOgFwIAIfkECQQAHgAsAAAAACMAIwAABbWgJ45kaZ5oqq5s675wLM90baPBvS6MTgoKgqjxEBEihZuAsRAxHKJHJXk7NAwBB8RzsPRqBYFo4RgkFALKxMhAxAiKBdXtAXgah4Eis2nIBgcLCSgVGxMKNYAoD4MzAgI5KgQHCAhULQUKmgmRJgUaIhwWLwIEBQQDKQEKDxEQCXYxnSUBcjapKAIcHUg+JgkUHRx+YB6zIw4YEMc2QiMBzDB0HgbGvifR19rb3N3e3+Dh4ikhADs=') no-repeat center; - width: 100%; - height: 100%; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-info { - position: absolute; - bottom: -10%; - left: 0; - width: 100%; - color: #fff; - padding: 6px 10px; - background: -moz-linear-gradient(bottom,rgba(0,0,0,1) 0,rgba(0,0,0,0) 100%); - background: -webkit-linear-gradient(bottom,rgba(0,0,0,1) 0,rgba(0,0,0,0) 100%); - background: -o-linear-gradient(bottom,rgba(0,0,0,1) 0,rgba(0,0,0,0) 100%); - background: -ms-linear-gradient(bottom,rgba(0,0,0,1) 0,rgba(0,0,0,0) 100%); - background: linear-gradient(to top,rgba(0,0,0,1) 0,rgba(0,0,0,0) 100%); - z-index: 9; - opacity: 0; - filter: alpha(opacity(0)); - -webkit-transition: all 0.12s; - -moz-transition: all 0.12s; - transition: all 0.12s; -} - -.jFiler-items-grid .jFiler-no-thumbnail.jFiler-item .jFiler-item-container .jFiler-item-info { - background: rgba(0,0,0,0.55); -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-thumb:hover .jFiler-item-info { - bottom: 0; - opacity: 1; - filter: aplpha(opacity(100)); -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-info .jFiler-item-title { - display: block; - font-weight: bold; - word-break: break-all; - line-height: 1; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-info .jFiler-item-others { - display: inline-block; - font-size: 10px; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-assets { - margin-top: 10px; - color: #999; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-assets .text-success { - color: #3C763D -} - -.jFiler-items-grid .jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-assets .text-error { - color: #A94442 -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-assets .jFiler-jProgressBar { - width: 120px; - margin-left: -5px; -} - -.jFiler-items-grid .jFiler-item .jFiler-item-container .jFiler-item-assets .jFiler-item-others { - font-size: 12px; -} - -.jFiler-items-grid .jFiler-item-trash-action:hover { - cursor: pointer; - color: #d9534f; -} \ No newline at end of file diff --git a/hal-core/resources/web/css/lib/svg.select.css b/hal-core/resources/web/css/lib/svg.select.css deleted file mode 100644 index 18888ab3..00000000 --- a/hal-core/resources/web/css/lib/svg.select.css +++ /dev/null @@ -1,44 +0,0 @@ -.svg_select_points_lt{ - cursor: nw-resize; -} -.svg_select_points_rt{ - cursor: ne-resize; -} -.svg_select_points_rb{ - cursor: se-resize; -} -.svg_select_points_lb{ - cursor: sw-resize; -} -.svg_select_points_t{ - cursor: n-resize; -} -.svg_select_points_r{ - cursor: e-resize; -} -.svg_select_points_b{ - cursor: s-resize; -} -.svg_select_points_l{ - cursor: w-resize; -} - -.svg_select_points_rot{ - stroke-width:1; - stroke:black; - fill: #F9FFED; -} - -.svg_select_points_point{ - cursor: move; -} - -.svg_select_boundingRect{ - stroke-width:1; - fill:gray; - stroke-dasharray:10 10; - stroke:black; - stroke-opacity:0.8; - fill-opacity:0.1; - pointer-events:none; /* This ons is needed if you want to deselect or drag the shape*/ -} \ No newline at end of file diff --git a/hal-core/resources/web/css/lib/svg.select.min.css b/hal-core/resources/web/css/lib/svg.select.min.css deleted file mode 100644 index d8345130..00000000 --- a/hal-core/resources/web/css/lib/svg.select.min.css +++ /dev/null @@ -1 +0,0 @@ -.svg_select_points_lt{cursor:nw-resize}.svg_select_points_rt{cursor:ne-resize}.svg_select_points_rb{cursor:se-resize}.svg_select_points_lb{cursor:sw-resize}.svg_select_points_t{cursor:n-resize}.svg_select_points_r{cursor:e-resize}.svg_select_points_b{cursor:s-resize}.svg_select_points_l{cursor:w-resize}.svg_select_points_rot{stroke-width:1;stroke:#000;fill:#f9ffed}.svg_select_points_point{cursor:move}.svg_select_boundingRect{stroke-width:1;fill:gray;stroke-dasharray:10 10;stroke:#000;stroke-opacity:.8;fill-opacity:.1;pointer-events:none} \ No newline at end of file diff --git a/hal-core/resources/web/event_config.tmpl b/hal-core/resources/web/event_config.tmpl deleted file mode 100644 index 38cbf22d..00000000 --- a/hal-core/resources/web/event_config.tmpl +++ /dev/null @@ -1,184 +0,0 @@ -

Event Configuration

- -
-
-
Local Events
-
-

This is a local list of events connected to this node.

- - - - - - - - - - {{#localEvents}} - - - - - - - - {{/localEvents}} -
#NameTypeConfiguration - -
{{.getId()}}{{.getName()}}{{.getType()}}{{.getDeviceConfig()}} -
- - -
- - - -
-
-
- -
-

Events that has been automatically detected.

- - - - - - - - - {{#detectedEvents}} - - - - - - - - {{/detectedEvents}} -
TypeDateDataConfiguration -
-
- - - -
-
-
{{.getType()}}{{.getDeviceData().getTimestamp()}}{{.getDeviceData()}}{{.getDeviceConfig()}} -
- -
-
-
-
-
- - - - - - - - - diff --git a/hal-core/resources/web/event_detail.tmpl b/hal-core/resources/web/event_detail.tmpl deleted file mode 100644 index e1466f0d..00000000 --- a/hal-core/resources/web/event_detail.tmpl +++ /dev/null @@ -1,79 +0,0 @@ -

Details for {{event.getName()}}

- -
-
-
Configuration
-
- - - - - - - - - - - - - - - - - - - - - - - - {{#event.getDeviceConfigurator().getConfiguration()}} - - - - - {{/event.getDeviceConfigurator().getConfiguration()}} -
Event ID:{{event.getId()}}
Name:{{event.getName()}}
Type:{{event.getDeviceConfig().getClass().getSimpleName()}}
Owner:{{event.getUser().getUsername()}}

State: -
- - - -
- -
-
-
{{.getNiceName()}}:{{.getString()}}
-
-
-
- -
-
-
History data
-
- - - - - - - {{#history}} - - - - - {{/history}} -
TimestampRaw Data
{{.timestamp}}{{.data}}
-
-
-
- - \ No newline at end of file diff --git a/hal-core/resources/web/favicon.ico b/hal-core/resources/web/favicon.ico deleted file mode 100644 index e9d61583..00000000 Binary files a/hal-core/resources/web/favicon.ico and /dev/null differ diff --git a/hal-core/resources/web/fonts/glyphicons-halflings-regular.eot b/hal-core/resources/web/fonts/glyphicons-halflings-regular.eot deleted file mode 100644 index b93a4953..00000000 Binary files a/hal-core/resources/web/fonts/glyphicons-halflings-regular.eot and /dev/null differ diff --git a/hal-core/resources/web/fonts/glyphicons-halflings-regular.svg b/hal-core/resources/web/fonts/glyphicons-halflings-regular.svg deleted file mode 100644 index 94fb5490..00000000 --- a/hal-core/resources/web/fonts/glyphicons-halflings-regular.svg +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hal-core/resources/web/fonts/glyphicons-halflings-regular.ttf b/hal-core/resources/web/fonts/glyphicons-halflings-regular.ttf deleted file mode 100644 index 1413fc60..00000000 Binary files a/hal-core/resources/web/fonts/glyphicons-halflings-regular.ttf and /dev/null differ diff --git a/hal-core/resources/web/fonts/glyphicons-halflings-regular.woff b/hal-core/resources/web/fonts/glyphicons-halflings-regular.woff deleted file mode 100644 index 9e612858..00000000 Binary files a/hal-core/resources/web/fonts/glyphicons-halflings-regular.woff and /dev/null differ diff --git a/hal-core/resources/web/fonts/glyphicons-halflings-regular.woff2 b/hal-core/resources/web/fonts/glyphicons-halflings-regular.woff2 deleted file mode 100644 index 64539b54..00000000 Binary files a/hal-core/resources/web/fonts/glyphicons-halflings-regular.woff2 and /dev/null differ diff --git a/hal-core/resources/web/img/favicon.svg b/hal-core/resources/web/img/favicon.svg deleted file mode 100644 index bb6996a5..00000000 --- a/hal-core/resources/web/img/favicon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/hal-core/resources/web/img/lightbulb_off.svg b/hal-core/resources/web/img/lightbulb_off.svg deleted file mode 100644 index fcd6bad5..00000000 --- a/hal-core/resources/web/img/lightbulb_off.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - -image/svg+xml - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hal-core/resources/web/img/lightbulb_on.svg b/hal-core/resources/web/img/lightbulb_on.svg deleted file mode 100644 index 12a44ab5..00000000 --- a/hal-core/resources/web/img/lightbulb_on.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hal-core/resources/web/img/temperature.svg b/hal-core/resources/web/img/temperature.svg deleted file mode 100644 index 68a0864d..00000000 --- a/hal-core/resources/web/img/temperature.svg +++ /dev/null @@ -1,95 +0,0 @@ - - - -image/svg+xml - - - - - - - - - - - \ No newline at end of file diff --git a/hal-core/resources/web/js/hal.js b/hal-core/resources/web/js/hal.js deleted file mode 100644 index e731b2e7..00000000 --- a/hal-core/resources/web/js/hal.js +++ /dev/null @@ -1,214 +0,0 @@ -// -------------------------------------------------------- -// Autostart -// -------------------------------------------------------- - -"use strict"; - -$(function(){ - $(".toggle-switch").bootstrapSwitch({inverse: true, size: "mini"}); - - $(".timestamp").relTimestamp(); -}); - -// -------------------------------------------------------- -// JQuery helper functions -// -------------------------------------------------------- - -// $.attr() # returns all attributes of an element -(function(old) { - $.fn.attr = function() { - if(arguments.length === 0) { - if(this.length === 0) { - return null; - } - - let obj = {}; - $.each(this[0].attributes, function() { - if(this.specified) { - obj[this.name] = this.value; - } - }); - return obj; - } - - return old.apply(this, arguments); - }; -})($.fn.attr); - -// -------------------------------------------------------- -// Timestamps -// -------------------------------------------------------- - -// Converts all timestamps to human readable time and date -$.fn.relTimestamp = function() { - return this.each(function() { - let timestamp = parseInt($(this).text()); - - $(this).text(getRelTimestamp(timestamp)); - return this; - }); -}; - -// Converts all timestamps to human readable time and date -function getRelTimestamp(timestamp) { - if (timestamp == null) - return ""; - - let timestampNow = Date.now(); - let timeDiff = timestampNow - timestamp; - - if(timeDiff < 10 * 60 * 1000) // less than 10 min - return moment(timestamp).fromNow(); - else if(timeDiff < 24 * 60 * 60 * 1000) // less than 24 hours - return moment(timestamp).fromNow() + " ("+moment(timestamp).format("HH:mm")+")"; - else - return moment(timestamp).format("YYYY-MM-DD HH:mm"); -} - -// -------------------------------------------------------- -// Chart functions -// -------------------------------------------------------- - -function createChart(elementId, url, updateTime=-1){ - let tickConf = {count: 20}; - if (updateTime < 60*60*1000) - tickConf['format'] = '%H:%M'; - else if (updateTime < 24*60*60*1000) - tickConf['format'] = '%Y-%m-%d %H:%M'; - else - tickConf['format'] = '%Y-%m-%d'; - - - var chart = c3.generate({ - bindto: elementId, - data: {json: []}, // set empty data, data will be loaded later - axis : { - x : { - type : 'timeseries', - label: 'Timestamp', - tick: tickConf, - }, - y: { - label: 'Power (kWh)', - min: 0, - }, - y2: { - show: true, - label: 'Temperature (C)', - min: 0, - } - }, - grid: { - y: {show: true} - }, - point: { - show: false - } - }); - - updateChart(chart, url, updateTime); - $(window).focus(function(e) { - updateChart(chart, url); - }); -} -function updateChart(chart, url, updateTime=-1){ - console.log('Updating chart: ' + chart.element.id); - - $.getJSON(url, function(json) { - chart.load(getChartData(json)); - }); - - if (updateTime > 0) { - setTimeout(function() { - updateChart(chart, url, updateTime); - }, updateTime); - } -} -function getChartData(json){ - let dataXaxis = {}; - let dataYaxis = {}; - let data = []; - let labels = []; - - json.forEach(function(sensor, i) { - var index = 'data' + i; - labels[index] = sensor.user + ': ' + sensor.name; - dataXaxis[index] = 'data' + i + 'x'; - data.push([index + 'x'].concat(sensor.aggregate.timestamps)); - data.push([index].concat(sensor.aggregate.data)); - - if (sensor.type == 'PowerConsumptionSensorData') - dataYaxis[index] = 'y'; - else //if (sensor.type == "TemperatureSensorData") - dataYaxis[index] = 'y2'; - }); - - return { - xs: dataXaxis, - columns: data, - names: labels, - type: 'spline', - axes: dataYaxis, - unload: true, - }; -} - -// -------------------------------------------------------- -// Dynamic forms -// -------------------------------------------------------- - -var dynamicConf = {}; - -function initDynamicModalForm(modalId, formTemplateId = null, templateID = null){ - // read in all configurations into global variable (to skip naming issues) - if (formTemplateId != null) { - dynamicConf[formTemplateId] = []; - $("#" + templateID + " div").each(function(){ - dynamicConf[formTemplateId][$(this).prop("id")] = $(this).html(); - }); - - // Update dynamic inputs - $("#" + modalId + " select[name=type]").change(function(){ - $("#" + modalId + " #" + formTemplateId).html(dynamicConf[formTemplateId][$(this).val()]); - }); - } - - // click event - $("#" + modalId).on('show.bs.modal', function (event) { - let button = $(event.relatedTarget); - let modal = $(this); - - modal.find(" input, select").val('').change(); // Reset all inputs - - // Set dynamic form data - $.each(button.attr(), function(fieldName, value) { - if(fieldName.startsWith("data-")) { - fieldName = fieldName.substring(5); // remove prefix data- - - // Case-insensitive search - var input = modal.find("input, select").filter(function() { - if (this.name.toLowerCase() == fieldName) { - if (this.type == "hidden" && modal.find("input[type=checkbox][name=" + fieldName + "]").length > 0) - return false; // Workaround for the default(false) boolean input - return true; - } - return false; - }); - - if (input.length > 0) { - if (input.prop("type") == "checkbox") { // special handling for checkboxes - input.prop("value", "true"); - input.prop("checked", value == "true"); - - if (modal.find("input[type=hidden][name=" + fieldName + "]") == null) { - // Add default false value as a unchecked checkbox is not included in the post - input.parent().prepend(""); - } - } else { - input.val(value).change(); - } - } - } - }); - }); -} \ No newline at end of file diff --git a/hal-core/resources/web/js/hal_alert.js b/hal-core/resources/web/js/hal_alert.js deleted file mode 100644 index e2e9baa7..00000000 --- a/hal-core/resources/web/js/hal_alert.js +++ /dev/null @@ -1,86 +0,0 @@ -// -------------------------------------------------------- -// Autostart -// -------------------------------------------------------- - -"use strict"; - -var alertDivId = "alert-container" -var alertTemplate = { - ERROR: ` -
- - -   - -
`, - WARNING: ` -
- - -   - -
`, - SUCCESS: ` -
- - -   - -
`, - INFO: ` -
- - -   - -
` -} - -$(function(){ - updateAlerts(); - - setInterval(function() { - updateAlerts(); - }, 3000); // 3 sec -}); - -function updateAlerts() { - fetch('/api/alert?action=poll') - .then(response => response.json()) - .then(data => { - data.forEach(alert => { - var alertElement = $("#alert-id-" + alert.id); - - if (alertElement.length <= 0) { - alertElement = $(alertTemplate[alert.level]); - $("#" + alertDivId).append(alertElement); - - alertElement.attr("id", "alert-id-" + alert.id); - alertElement.data("alert-id", alert.id); - alertElement.find(".close").click(dismissEvent); - } - - alertElement.find(".alert-title").html(alert.title); - alertElement.find(".alert-description").html(alert.description); - alertElement.find(".timestamp").relTimestamp(); - }); - }); -} - -function dismissEvent(e) { - dismissAlert($(e.target).parent().parent().data("alert-id")); -} -function dismissAlert(id) { - fetch('/api/alert?action=dismiss&id=' + id) - .then(response => response.json()) - .then(data => { - }); -} \ No newline at end of file diff --git a/hal-core/resources/web/js/hal_map.js b/hal-core/resources/web/js/hal_map.js deleted file mode 100644 index d05f22a4..00000000 --- a/hal-core/resources/web/js/hal_map.js +++ /dev/null @@ -1,306 +0,0 @@ -"use strict"; - -var svg; -var data = { - rooms: [], - sensors: [], - events: [] -}; -var editModeEnabled = false; - -$(function(){ - // ------------------------------------------ - // Setup map - // ------------------------------------------ - - svg = SVG('map'); - - // Initialize events - - $("#button-edit").click(function() { - editMode(true); - }); - $("#button-save").click(function() { - saveMap(); - editMode(false); - fetchData(drawMap); - }); - $("#button-cancel").click(function() { - editMode(false); - fetchData(drawMap); - }); - - // Initialize background image uploader - - $("#button-bg-edit").click(function() { - // Reset modal - $('#bg-file-input').parent().show(); - if ($("#file_input").prop("jFiler") != null) - $("#file_input").prop("jFiler").reset(); - $('#bg-file-progress').parent().hide(); - $('#bgUploadModal').modal('show'); - }); - $('#bg-file-input').filer({ - limit: 1, - extensions: ['jpg','png','svg','gif'], - maxSize: 3, // in MB - uploadFile: { - url: "", - type: 'POST', - enctype: 'multipart/form-data', - beforeSend: function(){ - $('#bg-file-input').parent().hide(); - $('#bg-file-progress').parent().show(); - }, - success: function(data, el){ - $('#bgUploadModal').modal('hide'); - drawMap(); - }, - error: function(el){ - $("#bg-file-progress").addClass("progress-bar-danger"); - }, - onProgress: function(t){ - $("#bg-file-progress").css("width", t + "%"); - }, - } - }); - - // ------------------------------------------ - // Start draw loop - // ------------------------------------------ - - fetchData(drawMap); - - setInterval(function() { - if (editModeEnabled == false) { - fetchData(drawMap); - } - }, 3000); // 3 sec - //}, 10000); // 10 sec - -}); - -// ---------------------------------------------- -// Events -// ---------------------------------------------- - -function editMode(enable){ - if (editModeEnabled == enable) { - return; - } - - editModeEnabled = enable; - - if (editModeEnabled) { - $('.edit-mode').show(); - $('.view-mode').hide(); - $('#map').css('border-color', '#6eb16e'); - - svg.select('.draggable').draggable(true); - //svg.select('.resizable').on('click', selectEvent, false); - svg.select('.resizable').selectize({ - points: ['rt', 'lb', 'rb'], // Add selection points on the corners - rotationPoint: false - }).resize() - } else { - $('.edit-mode').hide(); - $('.view-mode').show(); - $('#map').css('border-color', ''); - - svg.select('.draggable').draggable(false); - svg.select('resizable').selectize(false); - } -} - -function beforeDragEvent(e) { - if (editModeEnabled == false) { - e.preventDefault(); // Prevent drag - } -} - -function selectEvent(e) { - if (editModeEnabled == true) { - e.target.selectize({ - points: ['rt', 'lb', 'rb'], // Add selection points on the corners - rotationPoint: false - }).resize(); - } -} - -// -------------------------------------- -// Draw -// -------------------------------------- - -function drawMap() { - // Reset map - svg.clear(); - - // Background - - if (svg.select(".bg-image").length() <= 0) { - var bgImage = svg.image("?bgimage").addClass("bg-image") - .x(0) - .y(0) - .width("100%") - .height("100%"); - } - - // Rooms - - if (data.rooms != null) { - $.each(data.rooms, function(i, room) { - svg.select("#room-" + room.id).remove(); - - var group = svg.group(); - - group.text(room.name).move(5, 5).fill('#999'); - var rect = group.rect(room.map.width, room.map.height); - setAlertStyle(rect, (room.alert == null ? null : room.alert.level)); - rect.addClass("resizable"); - - group.addClass("room") - .attr("id", "room-" + room.id) - .attr("room-id", room.id) - .x(room.map.x) - .y(room.map.y) - .addClass("draggable"); - }); - } - - // Sensors - - if (data.sensors != null) { - $.each(data.sensors, function(i, sensor) { - svg.select("#sensor-" + sensor.id).remove(); - - var group = svg.group(); - group.element('title').words(sensor.name); - - group.text(sensor.data.valueStr).move(45, 15).fill('#999'); - group.image("/img/temperature.svg").size(50, 50); - - group.addClass("sensor") - .attr("id", "sensor-" + sensor.id) - .attr("sensor-id", sensor.id) - .x(sensor.map.x) - .y(sensor.map.y) - .addClass("draggable"); - }); - } - - // Events - - if (data.events != null) { - $.each(data.events, function(i, event) { - svg.select("#event-" + event.id).remove(); - - var group = svg.group(); - group.element('title').words(event.name); - - var img = "/img/lightbulb_off.svg"; - if (event.data.valueStr == "ON") - img = "/img/lightbulb_on.svg"; - group.image(img).size(50, 50); - - group.addClass("event") - .attr("id", "event-" + event.id) - .attr("event-id", event.id) - .x(event.map.x) - .y(event.map.y) - .addClass("draggable"); - }); - } -} - -// ---------------------------------------------- -// Load and Store data -// ---------------------------------------------- - -async function fetchData(callback) { - await fetch('/api/room') - .then(response => response.json()) - .then(json => { - data.rooms = json; - }) - - await fetch('/api/sensor') - .then(response => response.json()) - .then(json => { - data.sensors = json; - }) - - await fetch('/api/event') - .then(response => response.json()) - .then(json => { - data.events = json; - }) - - callback(); -} - -function saveMap(){ - svg.select(".room").each(function(){ - saveDevice(this, "room", "room-id"); - }); - svg.select(".sensor").each(function(){ - saveDevice(this, "sensor", "sensor-id"); - }); - svg.select(".event").each(function(){ - saveDevice(this, "event", "event-id"); - }); -} -function saveDevice(element, type, id) { - var data = { - action: "save", - id: element.attr(id), - type: type, - x: element.x(), - y: element.y() - }; - - var resizable = element.select(".resizable"); - if (resizable.length() > 0) { - data.width = resizable.get(0).width(); - data.height = resizable.get(0).height(); - } - - $.ajax({ - async: false, - dataType: "json", - url: "/api/map?", - data: data - }); -} - -// ---------------------------------------------- -// Colors -// ---------------------------------------------- - -function setAlertStyle(target, level=null) { - target.addClass("pulse-border"); - target.fill('none'); - - switch(level) { - case "ERROR": - target.stroke({opacity: 1, color: '#f00'}); - break; - case "WARNING": - target.stroke({opacity: 1, color: '#ffa500'}); - break; - case "SUCCESS": - target.stroke({opacity: 1, color: '#90EE90'}); - break; - case "INFO": - target.stroke({opacity: 1, color: '#87CEFA'}); - break; - - default: - target.removeClass("pulse-border"); - target.stroke({ - color: '#000', - opacity: 0.6, - width: 3 - });; - break; - } -} \ No newline at end of file diff --git a/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE b/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE deleted file mode 100644 index bc6fc511..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Javi Aguilar - -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. diff --git a/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE.txt b/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE.txt deleted file mode 100644 index bc6fc511..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Javi Aguilar - -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. diff --git a/hal-core/resources/web/js/lib/bootstrap-colorpicker.js b/hal-core/resources/web/js/lib/bootstrap-colorpicker.js deleted file mode 100644 index e2fd15da..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-colorpicker.js +++ /dev/null @@ -1,6252 +0,0 @@ -/*! - * Bootstrap Colorpicker - Bootstrap Colorpicker is a modular color picker plugin for Bootstrap 4. - * @package bootstrap-colorpicker - * @version v3.2.0 - * @license MIT - * @link https://itsjavi.com/bootstrap-colorpicker/ - * @link https://github.com/itsjavi/bootstrap-colorpicker.git - */ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("jquery")); - else if(typeof define === 'function' && define.amd) - define("bootstrap-colorpicker", ["jquery"], factory); - else if(typeof exports === 'object') - exports["bootstrap-colorpicker"] = factory(require("jquery")); - else - root["bootstrap-colorpicker"] = factory(root["jQuery"]); -})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 7); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE__0__; - -/***/ }), -/* 1 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Colorpicker extension class. - */ -var Extension = function () { - /** - * @param {Colorpicker} colorpicker - * @param {Object} options - */ - function Extension(colorpicker) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, Extension); - - /** - * The colorpicker instance - * @type {Colorpicker} - */ - this.colorpicker = colorpicker; - /** - * Extension options - * - * @type {Object} - */ - this.options = options; - - if (!(this.colorpicker.element && this.colorpicker.element.length)) { - throw new Error('Extension: this.colorpicker.element is not valid'); - } - - this.colorpicker.element.on('colorpickerCreate.colorpicker-ext', _jquery2.default.proxy(this.onCreate, this)); - this.colorpicker.element.on('colorpickerDestroy.colorpicker-ext', _jquery2.default.proxy(this.onDestroy, this)); - this.colorpicker.element.on('colorpickerUpdate.colorpicker-ext', _jquery2.default.proxy(this.onUpdate, this)); - this.colorpicker.element.on('colorpickerChange.colorpicker-ext', _jquery2.default.proxy(this.onChange, this)); - this.colorpicker.element.on('colorpickerInvalid.colorpicker-ext', _jquery2.default.proxy(this.onInvalid, this)); - this.colorpicker.element.on('colorpickerShow.colorpicker-ext', _jquery2.default.proxy(this.onShow, this)); - this.colorpicker.element.on('colorpickerHide.colorpicker-ext', _jquery2.default.proxy(this.onHide, this)); - this.colorpicker.element.on('colorpickerEnable.colorpicker-ext', _jquery2.default.proxy(this.onEnable, this)); - this.colorpicker.element.on('colorpickerDisable.colorpicker-ext', _jquery2.default.proxy(this.onDisable, this)); - } - - /** - * Function called every time a new color needs to be created. - * Return false to skip this resolver and continue with other extensions' ones - * or return anything else to consider the color resolved. - * - * @param {ColorItem|String|*} color - * @param {boolean} realColor if true, the color should resolve into a real (not named) color code - * @return {ColorItem|String|*} - */ - - - _createClass(Extension, [{ - key: 'resolveColor', - value: function resolveColor(color) { - var realColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - return false; - } - - /** - * Method called after the colorpicker is created - * - * @listens Colorpicker#colorpickerCreate - * @param {Event} event - */ - - }, { - key: 'onCreate', - value: function onCreate(event) {} - // to be extended - - - /** - * Method called after the colorpicker is destroyed - * - * @listens Colorpicker#colorpickerDestroy - * @param {Event} event - */ - - }, { - key: 'onDestroy', - value: function onDestroy(event) { - this.colorpicker.element.off('.colorpicker-ext'); - } - - /** - * Method called after the colorpicker is updated - * - * @listens Colorpicker#colorpickerUpdate - * @param {Event} event - */ - - }, { - key: 'onUpdate', - value: function onUpdate(event) {} - // to be extended - - - /** - * Method called after the colorpicker color is changed - * - * @listens Colorpicker#colorpickerChange - * @param {Event} event - */ - - }, { - key: 'onChange', - value: function onChange(event) {} - // to be extended - - - /** - * Method called when the colorpicker color is invalid - * - * @listens Colorpicker#colorpickerInvalid - * @param {Event} event - */ - - }, { - key: 'onInvalid', - value: function onInvalid(event) {} - // to be extended - - - /** - * Method called after the colorpicker is hidden - * - * @listens Colorpicker#colorpickerHide - * @param {Event} event - */ - - }, { - key: 'onHide', - value: function onHide(event) {} - // to be extended - - - /** - * Method called after the colorpicker is shown - * - * @listens Colorpicker#colorpickerShow - * @param {Event} event - */ - - }, { - key: 'onShow', - value: function onShow(event) {} - // to be extended - - - /** - * Method called after the colorpicker is disabled - * - * @listens Colorpicker#colorpickerDisable - * @param {Event} event - */ - - }, { - key: 'onDisable', - value: function onDisable(event) {} - // to be extended - - - /** - * Method called after the colorpicker is enabled - * - * @listens Colorpicker#colorpickerEnable - * @param {Event} event - */ - - }, { - key: 'onEnable', - value: function onEnable(event) { - // to be extended - } - }]); - - return Extension; -}(); - -exports.default = Extension; -module.exports = exports.default; - -/***/ }), -/* 2 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.ColorItem = exports.HSVAColor = undefined; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * Color manipulation class, specific for Bootstrap Colorpicker - */ - - -var _color = __webpack_require__(16); - -var _color2 = _interopRequireDefault(_color); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * HSVA color data class, containing the hue, saturation, value and alpha - * information. - */ -var HSVAColor = function () { - /** - * @param {number|int} h - * @param {number|int} s - * @param {number|int} v - * @param {number|int} a - */ - function HSVAColor(h, s, v, a) { - _classCallCheck(this, HSVAColor); - - this.h = isNaN(h) ? 0 : h; - this.s = isNaN(s) ? 0 : s; - this.v = isNaN(v) ? 0 : v; - this.a = isNaN(h) ? 1 : a; - } - - _createClass(HSVAColor, [{ - key: 'toString', - value: function toString() { - return this.h + ', ' + this.s + '%, ' + this.v + '%, ' + this.a; - } - }]); - - return HSVAColor; -}(); - -/** - * HSVA color manipulation - */ - - -var ColorItem = function () { - _createClass(ColorItem, [{ - key: 'api', - - - /** - * Applies a method of the QixColor API and returns a new Color object or - * the return value of the method call. - * - * If no argument is provided, the internal QixColor object is returned. - * - * @param {String} fn QixColor function name - * @param args QixColor function arguments - * @example let darkerColor = color.api('darken', 0.25); - * @example let luminosity = color.api('luminosity'); - * @example color = color.api('negate'); - * @example let qColor = color.api().negate(); - * @returns {ColorItem|QixColor|*} - */ - value: function api(fn) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - if (arguments.length === 0) { - return this._color; - } - - var result = this._color[fn].apply(this._color, args); - - if (!(result instanceof _color2.default)) { - // return result of the method call - return result; - } - - return new ColorItem(result, this.format); - } - - /** - * Returns the original ColorItem constructor data, - * plus a 'valid' flag to know if it's valid or not. - * - * @returns {{color: *, format: String, valid: boolean}} - */ - - }, { - key: 'original', - get: function get() { - return this._original; - } - - /** - * @param {ColorItem|HSVAColor|QixColor|String|*|null} color Color data - * @param {String|null} format Color model to convert to by default. Supported: 'rgb', 'hsl', 'hex'. - */ - - }], [{ - key: 'HSVAColor', - - - /** - * Returns the HSVAColor class - * - * @static - * @example let colorData = new ColorItem.HSVAColor(360, 100, 100, 1); - * @returns {HSVAColor} - */ - get: function get() { - return HSVAColor; - } - }]); - - function ColorItem() { - var color = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - var format = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - - _classCallCheck(this, ColorItem); - - this.replace(color, format); - } - - /** - * Replaces the internal QixColor object with a new one. - * This also replaces the internal original color data. - * - * @param {ColorItem|HSVAColor|QixColor|String|*|null} color Color data to be parsed (if needed) - * @param {String|null} format Color model to convert to by default. Supported: 'rgb', 'hsl', 'hex'. - * @example color.replace('rgb(255,0,0)', 'hsl'); - * @example color.replace(hsvaColorData); - */ - - - _createClass(ColorItem, [{ - key: 'replace', - value: function replace(color) { - var format = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - - format = ColorItem.sanitizeFormat(format); - - /** - * @type {{color: *, format: String}} - * @private - */ - this._original = { - color: color, - format: format, - valid: true - }; - /** - * @type {QixColor} - * @private - */ - this._color = ColorItem.parse(color); - - if (this._color === null) { - this._color = (0, _color2.default)(); - this._original.valid = false; - return; - } - - /** - * @type {*|string} - * @private - */ - this._format = format ? format : ColorItem.isHex(color) ? 'hex' : this._color.model; - } - - /** - * Parses the color returning a Qix Color object or null if cannot be - * parsed. - * - * @param {ColorItem|HSVAColor|QixColor|String|*|null} color Color data - * @example let qColor = ColorItem.parse('rgb(255,0,0)'); - * @static - * @returns {QixColor|null} - */ - - }, { - key: 'isValid', - - - /** - * Returns true if the color is valid, false if not. - * - * @returns {boolean} - */ - value: function isValid() { - return this._original.valid === true; - } - - /** - * Hue value from 0 to 360 - * - * @returns {int} - */ - - }, { - key: 'setHueRatio', - - - /** - * Sets the hue ratio, where 1.0 is 0, 0.5 is 180 and 0.0 is 360. - * - * @ignore - * @param {number} h Ratio from 1.0 to 0.0 - */ - value: function setHueRatio(h) { - this.hue = (1 - h) * 360; - } - - /** - * Sets the saturation value - * - * @param {int} value Integer from 0 to 100 - */ - - }, { - key: 'setSaturationRatio', - - - /** - * Sets the saturation ratio, where 1.0 is 100 and 0.0 is 0. - * - * @ignore - * @param {number} s Ratio from 0.0 to 1.0 - */ - value: function setSaturationRatio(s) { - this.saturation = s * 100; - } - - /** - * Sets the 'value' channel value - * - * @param {int} value Integer from 0 to 100 - */ - - }, { - key: 'setValueRatio', - - - /** - * Sets the value ratio, where 1.0 is 0 and 0.0 is 100. - * - * @ignore - * @param {number} v Ratio from 1.0 to 0.0 - */ - value: function setValueRatio(v) { - this.value = (1 - v) * 100; - } - - /** - * Sets the alpha value. It will be rounded to 2 decimals. - * - * @param {int} value Float from 0.0 to 1.0 - */ - - }, { - key: 'setAlphaRatio', - - - /** - * Sets the alpha ratio, where 1.0 is 0.0 and 0.0 is 1.0. - * - * @ignore - * @param {number} a Ratio from 1.0 to 0.0 - */ - value: function setAlphaRatio(a) { - this.alpha = 1 - a; - } - - /** - * Sets the default color format - * - * @param {String} value Supported: 'rgb', 'hsl', 'hex' - */ - - }, { - key: 'isDesaturated', - - - /** - * Returns true if the saturation value is zero, false otherwise - * - * @returns {boolean} - */ - value: function isDesaturated() { - return this.saturation === 0; - } - - /** - * Returns true if the alpha value is zero, false otherwise - * - * @returns {boolean} - */ - - }, { - key: 'isTransparent', - value: function isTransparent() { - return this.alpha === 0; - } - - /** - * Returns true if the alpha value is numeric and less than 1, false otherwise - * - * @returns {boolean} - */ - - }, { - key: 'hasTransparency', - value: function hasTransparency() { - return this.hasAlpha() && this.alpha < 1; - } - - /** - * Returns true if the alpha value is numeric, false otherwise - * - * @returns {boolean} - */ - - }, { - key: 'hasAlpha', - value: function hasAlpha() { - return !isNaN(this.alpha); - } - - /** - * Returns a new HSVAColor object, based on the current color - * - * @returns {HSVAColor} - */ - - }, { - key: 'toObject', - value: function toObject() { - return new HSVAColor(this.hue, this.saturation, this.value, this.alpha); - } - - /** - * Alias of toObject() - * - * @returns {HSVAColor} - */ - - }, { - key: 'toHsva', - value: function toHsva() { - return this.toObject(); - } - - /** - * Returns a new HSVAColor object with the ratio values (from 0.0 to 1.0), - * based on the current color. - * - * @ignore - * @returns {HSVAColor} - */ - - }, { - key: 'toHsvaRatio', - value: function toHsvaRatio() { - return new HSVAColor(this.hue / 360, this.saturation / 100, this.value / 100, this.alpha); - } - - /** - * Converts the current color to its string representation, - * using the internal format of this instance. - * - * @returns {String} - */ - - }, { - key: 'toString', - value: function toString() { - return this.string(); - } - - /** - * Converts the current color to its string representation, - * using the given format. - * - * @param {String|null} format Format to convert to. If empty or null, the internal format will be used. - * @returns {String} - */ - - }, { - key: 'string', - value: function string() { - var format = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - - format = ColorItem.sanitizeFormat(format ? format : this.format); - - if (!format) { - return this._color.round().string(); - } - - if (this._color[format] === undefined) { - throw new Error('Unsupported color format: \'' + format + '\''); - } - - var str = this._color[format](); - - return str.round ? str.round().string() : str; - } - - /** - * Returns true if the given color values equals this one, false otherwise. - * The format is not compared. - * If any of the colors is invalid, the result will be false. - * - * @param {ColorItem|HSVAColor|QixColor|String|*|null} color Color data - * - * @returns {boolean} - */ - - }, { - key: 'equals', - value: function equals(color) { - color = color instanceof ColorItem ? color : new ColorItem(color); - - if (!color.isValid() || !this.isValid()) { - return false; - } - - return this.hue === color.hue && this.saturation === color.saturation && this.value === color.value && this.alpha === color.alpha; - } - - /** - * Creates a copy of this instance - * - * @returns {ColorItem} - */ - - }, { - key: 'getClone', - value: function getClone() { - return new ColorItem(this._color, this.format); - } - - /** - * Creates a copy of this instance, only copying the hue value, - * and setting the others to its max value. - * - * @returns {ColorItem} - */ - - }, { - key: 'getCloneHueOnly', - value: function getCloneHueOnly() { - return new ColorItem([this.hue, 100, 100, 1], this.format); - } - - /** - * Creates a copy of this instance setting the alpha to the max. - * - * @returns {ColorItem} - */ - - }, { - key: 'getCloneOpaque', - value: function getCloneOpaque() { - return new ColorItem(this._color.alpha(1), this.format); - } - - /** - * Converts the color to a RGB string - * - * @returns {String} - */ - - }, { - key: 'toRgbString', - value: function toRgbString() { - return this.string('rgb'); - } - - /** - * Converts the color to a Hexadecimal string - * - * @returns {String} - */ - - }, { - key: 'toHexString', - value: function toHexString() { - return this.string('hex'); - } - - /** - * Converts the color to a HSL string - * - * @returns {String} - */ - - }, { - key: 'toHslString', - value: function toHslString() { - return this.string('hsl'); - } - - /** - * Returns true if the color is dark, false otherwhise. - * This is useful to decide a text color. - * - * @returns {boolean} - */ - - }, { - key: 'isDark', - value: function isDark() { - return this._color.isDark(); - } - - /** - * Returns true if the color is light, false otherwhise. - * This is useful to decide a text color. - * - * @returns {boolean} - */ - - }, { - key: 'isLight', - value: function isLight() { - return this._color.isLight(); - } - - /** - * Generates a list of colors using the given hue-based formula or the given array of hue values. - * Hue formulas can be extended using ColorItem.colorFormulas static property. - * - * @param {String|Number[]} formula Examples: 'complementary', 'triad', 'tetrad', 'splitcomplement', [180, 270] - * @example let colors = color.generate('triad'); - * @example let colors = color.generate([45, 80, 112, 200]); - * @returns {ColorItem[]} - */ - - }, { - key: 'generate', - value: function generate(formula) { - var hues = []; - - if (Array.isArray(formula)) { - hues = formula; - } else if (!ColorItem.colorFormulas.hasOwnProperty(formula)) { - throw new Error('No color formula found with the name \'' + formula + '\'.'); - } else { - hues = ColorItem.colorFormulas[formula]; - } - - var colors = [], - mainColor = this._color, - format = this.format; - - hues.forEach(function (hue) { - var levels = [hue ? (mainColor.hue() + hue) % 360 : mainColor.hue(), mainColor.saturationv(), mainColor.value(), mainColor.alpha()]; - - colors.push(new ColorItem(levels, format)); - }); - - return colors; - } - }, { - key: 'hue', - get: function get() { - return this._color.hue(); - } - - /** - * Saturation value from 0 to 100 - * - * @returns {int} - */ - , - - - /** - * Sets the hue value - * - * @param {int} value Integer from 0 to 360 - */ - set: function set(value) { - this._color = this._color.hue(value); - } - }, { - key: 'saturation', - get: function get() { - return this._color.saturationv(); - } - - /** - * Value channel value from 0 to 100 - * - * @returns {int} - */ - , - set: function set(value) { - this._color = this._color.saturationv(value); - } - }, { - key: 'value', - get: function get() { - return this._color.value(); - } - - /** - * Alpha value from 0.0 to 1.0 - * - * @returns {number} - */ - , - set: function set(value) { - this._color = this._color.value(value); - } - }, { - key: 'alpha', - get: function get() { - var a = this._color.alpha(); - - return isNaN(a) ? 1 : a; - } - - /** - * Default color format to convert to when calling toString() or string() - * - * @returns {String} 'rgb', 'hsl', 'hex' or '' - */ - , - set: function set(value) { - // 2 decimals max - this._color = this._color.alpha(Math.round(value * 100) / 100); - } - }, { - key: 'format', - get: function get() { - return this._format ? this._format : this._color.model; - }, - set: function set(value) { - this._format = ColorItem.sanitizeFormat(value); - } - }], [{ - key: 'parse', - value: function parse(color) { - if (color instanceof _color2.default) { - return color; - } - - if (color instanceof ColorItem) { - return color._color; - } - - var format = null; - - if (color instanceof HSVAColor) { - color = [color.h, color.s, color.v, isNaN(color.a) ? 1 : color.a]; - } else { - color = ColorItem.sanitizeString(color); - } - - if (color === null) { - return null; - } - - if (Array.isArray(color)) { - format = 'hsv'; - } - - try { - return (0, _color2.default)(color, format); - } catch (e) { - return null; - } - } - - /** - * Sanitizes a color string, adding missing hash to hexadecimal colors - * and converting 'transparent' to a color code. - * - * @param {String|*} str Color string - * @example let colorStr = ColorItem.sanitizeString('ffaa00'); - * @static - * @returns {String|*} - */ - - }, { - key: 'sanitizeString', - value: function sanitizeString(str) { - if (!(typeof str === 'string' || str instanceof String)) { - return str; - } - - if (str.match(/^[0-9a-f]{2,}$/i)) { - return '#' + str; - } - - if (str.toLowerCase() === 'transparent') { - return '#FFFFFF00'; - } - - return str; - } - - /** - * Detects if a value is a string and a color in hexadecimal format (in any variant). - * - * @param {String} str - * @example ColorItem.isHex('rgba(0,0,0)'); // false - * @example ColorItem.isHex('ffaa00'); // true - * @example ColorItem.isHex('#ffaa00'); // true - * @static - * @returns {boolean} - */ - - }, { - key: 'isHex', - value: function isHex(str) { - if (!(typeof str === 'string' || str instanceof String)) { - return false; - } - - return !!str.match(/^#?[0-9a-f]{2,}$/i); - } - - /** - * Sanitizes a color format to one supported by web browsers. - * Returns an empty string of the format can't be recognised. - * - * @param {String|*} format - * @example ColorItem.sanitizeFormat('rgba'); // 'rgb' - * @example ColorItem.isHex('hex8'); // 'hex' - * @example ColorItem.isHex('invalid'); // '' - * @static - * @returns {String} 'rgb', 'hsl', 'hex' or ''. - */ - - }, { - key: 'sanitizeFormat', - value: function sanitizeFormat(format) { - switch (format) { - case 'hex': - case 'hex3': - case 'hex4': - case 'hex6': - case 'hex8': - return 'hex'; - case 'rgb': - case 'rgba': - case 'keyword': - case 'name': - return 'rgb'; - case 'hsl': - case 'hsla': - case 'hsv': - case 'hsva': - case 'hwb': // HWB this is supported by Qix Color, but not by browsers - case 'hwba': - return 'hsl'; - default: - return ''; - } - } - }]); - - return ColorItem; -}(); - -/** - * List of hue-based color formulas used by ColorItem.prototype.generate() - * - * @static - * @type {{complementary: number[], triad: number[], tetrad: number[], splitcomplement: number[]}} - */ - - -ColorItem.colorFormulas = { - complementary: [180], - triad: [0, 120, 240], - tetrad: [0, 90, 180, 270], - splitcomplement: [0, 72, 216] -}; - -exports.default = ColorItem; -exports.HSVAColor = HSVAColor; -exports.ColorItem = ColorItem; - -/***/ }), -/* 3 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * @module - */ - -// adjust these values accordingly to the sass vars - -Object.defineProperty(exports, "__esModule", { - value: true -}); -var sassVars = { - 'bar_size_short': 16, - 'base_margin': 6, - 'columns': 6 -}; - -var sliderSize = sassVars.bar_size_short * sassVars.columns + sassVars.base_margin * (sassVars.columns - 1); - -/** - * Colorpicker default options - */ -exports.default = { - /** - * Custom class to be added to the `.colorpicker-element` element - * - * @type {String|null} - * @default null - */ - customClass: null, - /** - * Sets a initial color, ignoring the one from the element/input value or the data-color attribute. - * - * @type {(String|ColorItem|boolean)} - * @default false - */ - color: false, - /** - * Fallback color to use when the given color is invalid. - * If false, the latest valid color will be used as a fallback. - * - * @type {String|ColorItem|boolean} - * @default false - */ - fallbackColor: false, - /** - * Forces an specific color format. If 'auto', it will be automatically detected the first time only, - * but if null it will be always recalculated. - * - * Note that the ending 'a' of the format meaning "alpha" has currently no effect, meaning that rgb is the same as - * rgba excepting if the alpha channel is disabled (see useAlpha). - * - * @type {('rgb'|'hex'|'hsl'|'auto'|null)} - * @default 'auto' - */ - format: 'auto', - /** - * Horizontal mode layout. - * - * If true, the hue and alpha channel bars will be rendered horizontally, above the saturation selector. - * - * @type {boolean} - * @default false - */ - horizontal: false, - /** - * Forces to show the colorpicker as an inline element. - * - * Note that if there is no container specified, the inline element - * will be added to the body, so you may want to set the container option. - * - * @type {boolean} - * @default false - */ - inline: false, - /** - * Container where the colorpicker is appended to in the DOM. - * - * If is a string (CSS selector), the colorpicker will be placed inside this container. - * If true, the `.colorpicker-element` element itself will be used as the container. - * If false, the document body is used as the container, unless it is a popover (in this case it is appended to the - * popover body instead). - * - * @type {String|boolean} - * @default false - */ - container: false, - /** - * Bootstrap Popover options. - * The trigger, content and html options are always ignored. - * - * @type {boolean} - * @default Object - */ - popover: { - animation: true, - placement: 'bottom', - fallbackPlacement: 'flip' - }, - /** - * If true, loads the 'debugger' extension automatically, which logs the events in the console - * @type {boolean} - * @default false - */ - debug: false, - /** - * Child CSS selector for the colorpicker input. - * - * @type {String} - * @default 'input' - */ - input: 'input', - /** - * Child CSS selector for the colorpicker addon. - * If it exists, the child element background will be changed on color change. - * - * @type {String} - * @default '.colorpicker-trigger, .colorpicker-input-addon' - */ - addon: '.colorpicker-input-addon', - /** - * If true, the input content will be replaced always with a valid color, - * if false, the invalid color will be left in the input, - * while the internal color object will still resolve into a valid one. - * - * @type {boolean} - * @default true - */ - autoInputFallback: true, - /** - * If true a hash will be prepended to hexadecimal colors. - * If false, the hash will be removed. - * This only affects the input values in hexadecimal format. - * - * @type {boolean} - * @default true - */ - useHashPrefix: true, - /** - * If true, the alpha channel bar will be displayed no matter what. - * - * If false, it will be always hidden and alpha channel will be disabled also programmatically, meaning that - * the selected or typed color will be always opaque. - * - * If null, the alpha channel will be automatically disabled/enabled depending if the initial color format supports - * alpha or not. - * - * @type {boolean} - * @default true - */ - useAlpha: true, - /** - * Colorpicker widget template - * @type {String} - * @example - * - *
- *
- *
- *
- *
- * - *
- *
- */ - template: '
\n
\n
\n
\n
\n \n
\n
', - /** - * - * Associative object with the extension class name and its config. - * Colorpicker comes with many bundled extensions: debugger, palette, preview and swatches (a superset of palette). - * - * @type {Object[]} - * @example - * extensions: [ - * { - * name: 'swatches' - * options: { - * colors: { - * 'primary': '#337ab7', - * 'success': '#5cb85c', - * 'info': '#5bc0de', - * 'warning': '#f0ad4e', - * 'danger': '#d9534f' - * }, - * namesAsValues: true - * } - * } - * ] - */ - extensions: [{ - name: 'preview', - options: { - showText: true - } - }], - /** - * Vertical sliders configuration - * @type {Object} - */ - sliders: { - saturation: { - selector: '.colorpicker-saturation', - maxLeft: sliderSize, - maxTop: sliderSize, - callLeft: 'setSaturationRatio', - callTop: 'setValueRatio' - }, - hue: { - selector: '.colorpicker-hue', - maxLeft: 0, - maxTop: sliderSize, - callLeft: false, - callTop: 'setHueRatio' - }, - alpha: { - selector: '.colorpicker-alpha', - childSelector: '.colorpicker-alpha-color', - maxLeft: 0, - maxTop: sliderSize, - callLeft: false, - callTop: 'setAlphaRatio' - } - }, - /** - * Horizontal sliders configuration - * @type {Object} - */ - slidersHorz: { - saturation: { - selector: '.colorpicker-saturation', - maxLeft: sliderSize, - maxTop: sliderSize, - callLeft: 'setSaturationRatio', - callTop: 'setValueRatio' - }, - hue: { - selector: '.colorpicker-hue', - maxLeft: sliderSize, - maxTop: 0, - callLeft: 'setHueRatio', - callTop: false - }, - alpha: { - selector: '.colorpicker-alpha', - childSelector: '.colorpicker-alpha-color', - maxLeft: sliderSize, - maxTop: 0, - callLeft: 'setAlphaRatio', - callTop: false - } - } -}; -module.exports = exports.default; - -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _Extension2 = __webpack_require__(1); - -var _Extension3 = _interopRequireDefault(_Extension2); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var defaults = { - /** - * Key-value pairs defining a color alias and its CSS color representation. - * - * They can also be just an array of values. In that case, no special names are used, only the real colors. - * - * @type {Object|Array} - * @default null - * @example - * { - * 'black': '#000000', - * 'white': '#ffffff', - * 'red': '#FF0000', - * 'default': '#777777', - * 'primary': '#337ab7', - * 'success': '#5cb85c', - * 'info': '#5bc0de', - * 'warning': '#f0ad4e', - * 'danger': '#d9534f' - * } - * - * @example ['#f0ad4e', '#337ab7', '#5cb85c'] - */ - colors: null, - /** - * If true, when a color swatch is selected the name (alias) will be used as input value, - * otherwise the swatch real color value will be used. - * - * @type {boolean} - * @default true - */ - namesAsValues: true -}; - -/** - * Palette extension - * @ignore - */ - -var Palette = function (_Extension) { - _inherits(Palette, _Extension); - - _createClass(Palette, [{ - key: 'colors', - - - /** - * @returns {Object|Array} - */ - get: function get() { - return this.options.colors; - } - }]); - - function Palette(colorpicker) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, Palette); - - var _this = _possibleConstructorReturn(this, (Palette.__proto__ || Object.getPrototypeOf(Palette)).call(this, colorpicker, _jquery2.default.extend(true, {}, defaults, options))); - - if (!Array.isArray(_this.options.colors) && _typeof(_this.options.colors) !== 'object') { - _this.options.colors = null; - } - return _this; - } - - /** - * @returns {int} - */ - - - _createClass(Palette, [{ - key: 'getLength', - value: function getLength() { - if (!this.options.colors) { - return 0; - } - - if (Array.isArray(this.options.colors)) { - return this.options.colors.length; - } - - if (_typeof(this.options.colors) === 'object') { - return Object.keys(this.options.colors).length; - } - - return 0; - } - }, { - key: 'resolveColor', - value: function resolveColor(color) { - var realColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - if (this.getLength() <= 0) { - return false; - } - - // Array of colors - if (Array.isArray(this.options.colors)) { - if (this.options.colors.indexOf(color) >= 0) { - return color; - } - if (this.options.colors.indexOf(color.toUpperCase()) >= 0) { - return color.toUpperCase(); - } - if (this.options.colors.indexOf(color.toLowerCase()) >= 0) { - return color.toLowerCase(); - } - return false; - } - - if (_typeof(this.options.colors) !== 'object') { - return false; - } - - // Map of objects - if (!this.options.namesAsValues || realColor) { - return this.getValue(color, false); - } - return this.getName(color, this.getName('#' + color)); - } - - /** - * Given a color value, returns the corresponding color name or defaultValue. - * - * @param {String} value - * @param {*} defaultValue - * @returns {*} - */ - - }, { - key: 'getName', - value: function getName(value) { - var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - - if (!(typeof value === 'string') || !this.options.colors) { - return defaultValue; - } - for (var name in this.options.colors) { - if (!this.options.colors.hasOwnProperty(name)) { - continue; - } - if (this.options.colors[name].toLowerCase() === value.toLowerCase()) { - return name; - } - } - return defaultValue; - } - - /** - * Given a color name, returns the corresponding color value or defaultValue. - * - * @param {String} name - * @param {*} defaultValue - * @returns {*} - */ - - }, { - key: 'getValue', - value: function getValue(name) { - var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - - if (!(typeof name === 'string') || !this.options.colors) { - return defaultValue; - } - if (this.options.colors.hasOwnProperty(name)) { - return this.options.colors[name]; - } - return defaultValue; - } - }]); - - return Palette; -}(_Extension3.default); - -exports.default = Palette; -module.exports = exports.default; - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] -}; - - -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { - -/* MIT license */ -var cssKeywords = __webpack_require__(5); - -// NOTE: conversions should only return primitive values (i.e. arrays, or -// values that give correct `typeof` results). -// do not use box values types (i.e. Number(), String(), etc.) - -var reverseKeywords = {}; -for (var key in cssKeywords) { - if (cssKeywords.hasOwnProperty(key)) { - reverseKeywords[cssKeywords[key]] = key; - } -} - -var convert = module.exports = { - rgb: {channels: 3, labels: 'rgb'}, - hsl: {channels: 3, labels: 'hsl'}, - hsv: {channels: 3, labels: 'hsv'}, - hwb: {channels: 3, labels: 'hwb'}, - cmyk: {channels: 4, labels: 'cmyk'}, - xyz: {channels: 3, labels: 'xyz'}, - lab: {channels: 3, labels: 'lab'}, - lch: {channels: 3, labels: 'lch'}, - hex: {channels: 1, labels: ['hex']}, - keyword: {channels: 1, labels: ['keyword']}, - ansi16: {channels: 1, labels: ['ansi16']}, - ansi256: {channels: 1, labels: ['ansi256']}, - hcg: {channels: 3, labels: ['h', 'c', 'g']}, - apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, - gray: {channels: 1, labels: ['gray']} -}; - -// hide .channels and .labels properties -for (var model in convert) { - if (convert.hasOwnProperty(model)) { - if (!('channels' in convert[model])) { - throw new Error('missing channels property: ' + model); - } - - if (!('labels' in convert[model])) { - throw new Error('missing channel labels property: ' + model); - } - - if (convert[model].labels.length !== convert[model].channels) { - throw new Error('channel and label counts mismatch: ' + model); - } - - var channels = convert[model].channels; - var labels = convert[model].labels; - delete convert[model].channels; - delete convert[model].labels; - Object.defineProperty(convert[model], 'channels', {value: channels}); - Object.defineProperty(convert[model], 'labels', {value: labels}); - } -} - -convert.rgb.hsl = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var min = Math.min(r, g, b); - var max = Math.max(r, g, b); - var delta = max - min; - var h; - var s; - var l; - - if (max === min) { - h = 0; - } else if (r === max) { - h = (g - b) / delta; - } else if (g === max) { - h = 2 + (b - r) / delta; - } else if (b === max) { - h = 4 + (r - g) / delta; - } - - h = Math.min(h * 60, 360); - - if (h < 0) { - h += 360; - } - - l = (min + max) / 2; - - if (max === min) { - s = 0; - } else if (l <= 0.5) { - s = delta / (max + min); - } else { - s = delta / (2 - max - min); - } - - return [h, s * 100, l * 100]; -}; - -convert.rgb.hsv = function (rgb) { - var rdif; - var gdif; - var bdif; - var h; - var s; - - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var v = Math.max(r, g, b); - var diff = v - Math.min(r, g, b); - var diffc = function (c) { - return (v - c) / 6 / diff + 1 / 2; - }; - - if (diff === 0) { - h = s = 0; - } else { - s = diff / v; - rdif = diffc(r); - gdif = diffc(g); - bdif = diffc(b); - - if (r === v) { - h = bdif - gdif; - } else if (g === v) { - h = (1 / 3) + rdif - bdif; - } else if (b === v) { - h = (2 / 3) + gdif - rdif; - } - if (h < 0) { - h += 1; - } else if (h > 1) { - h -= 1; - } - } - - return [ - h * 360, - s * 100, - v * 100 - ]; -}; - -convert.rgb.hwb = function (rgb) { - var r = rgb[0]; - var g = rgb[1]; - var b = rgb[2]; - var h = convert.rgb.hsl(rgb)[0]; - var w = 1 / 255 * Math.min(r, Math.min(g, b)); - - b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); - - return [h, w * 100, b * 100]; -}; - -convert.rgb.cmyk = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var c; - var m; - var y; - var k; - - k = Math.min(1 - r, 1 - g, 1 - b); - c = (1 - r - k) / (1 - k) || 0; - m = (1 - g - k) / (1 - k) || 0; - y = (1 - b - k) / (1 - k) || 0; - - return [c * 100, m * 100, y * 100, k * 100]; -}; - -/** - * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance - * */ -function comparativeDistance(x, y) { - return ( - Math.pow(x[0] - y[0], 2) + - Math.pow(x[1] - y[1], 2) + - Math.pow(x[2] - y[2], 2) - ); -} - -convert.rgb.keyword = function (rgb) { - var reversed = reverseKeywords[rgb]; - if (reversed) { - return reversed; - } - - var currentClosestDistance = Infinity; - var currentClosestKeyword; - - for (var keyword in cssKeywords) { - if (cssKeywords.hasOwnProperty(keyword)) { - var value = cssKeywords[keyword]; - - // Compute comparative distance - var distance = comparativeDistance(rgb, value); - - // Check if its less, if so set as closest - if (distance < currentClosestDistance) { - currentClosestDistance = distance; - currentClosestKeyword = keyword; - } - } - } - - return currentClosestKeyword; -}; - -convert.keyword.rgb = function (keyword) { - return cssKeywords[keyword]; -}; - -convert.rgb.xyz = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - - // assume sRGB - r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); - g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); - b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); - - var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - - return [x * 100, y * 100, z * 100]; -}; - -convert.rgb.lab = function (rgb) { - var xyz = convert.rgb.xyz(rgb); - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; -}; - -convert.hsl.rgb = function (hsl) { - var h = hsl[0] / 360; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var t1; - var t2; - var t3; - var rgb; - var val; - - if (s === 0) { - val = l * 255; - return [val, val, val]; - } - - if (l < 0.5) { - t2 = l * (1 + s); - } else { - t2 = l + s - l * s; - } - - t1 = 2 * l - t2; - - rgb = [0, 0, 0]; - for (var i = 0; i < 3; i++) { - t3 = h + 1 / 3 * -(i - 1); - if (t3 < 0) { - t3++; - } - if (t3 > 1) { - t3--; - } - - if (6 * t3 < 1) { - val = t1 + (t2 - t1) * 6 * t3; - } else if (2 * t3 < 1) { - val = t2; - } else if (3 * t3 < 2) { - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - } else { - val = t1; - } - - rgb[i] = val * 255; - } - - return rgb; -}; - -convert.hsl.hsv = function (hsl) { - var h = hsl[0]; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var smin = s; - var lmin = Math.max(l, 0.01); - var sv; - var v; - - l *= 2; - s *= (l <= 1) ? l : 2 - l; - smin *= lmin <= 1 ? lmin : 2 - lmin; - v = (l + s) / 2; - sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); - - return [h, sv * 100, v * 100]; -}; - -convert.hsv.rgb = function (hsv) { - var h = hsv[0] / 60; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var hi = Math.floor(h) % 6; - - var f = h - Math.floor(h); - var p = 255 * v * (1 - s); - var q = 255 * v * (1 - (s * f)); - var t = 255 * v * (1 - (s * (1 - f))); - v *= 255; - - switch (hi) { - case 0: - return [v, t, p]; - case 1: - return [q, v, p]; - case 2: - return [p, v, t]; - case 3: - return [p, q, v]; - case 4: - return [t, p, v]; - case 5: - return [v, p, q]; - } -}; - -convert.hsv.hsl = function (hsv) { - var h = hsv[0]; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var vmin = Math.max(v, 0.01); - var lmin; - var sl; - var l; - - l = (2 - s) * v; - lmin = (2 - s) * vmin; - sl = s * vmin; - sl /= (lmin <= 1) ? lmin : 2 - lmin; - sl = sl || 0; - l /= 2; - - return [h, sl * 100, l * 100]; -}; - -// http://dev.w3.org/csswg/css-color/#hwb-to-rgb -convert.hwb.rgb = function (hwb) { - var h = hwb[0] / 360; - var wh = hwb[1] / 100; - var bl = hwb[2] / 100; - var ratio = wh + bl; - var i; - var v; - var f; - var n; - - // wh + bl cant be > 1 - if (ratio > 1) { - wh /= ratio; - bl /= ratio; - } - - i = Math.floor(6 * h); - v = 1 - bl; - f = 6 * h - i; - - if ((i & 0x01) !== 0) { - f = 1 - f; - } - - n = wh + f * (v - wh); // linear interpolation - - var r; - var g; - var b; - switch (i) { - default: - case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; - } - - return [r * 255, g * 255, b * 255]; -}; - -convert.cmyk.rgb = function (cmyk) { - var c = cmyk[0] / 100; - var m = cmyk[1] / 100; - var y = cmyk[2] / 100; - var k = cmyk[3] / 100; - var r; - var g; - var b; - - r = 1 - Math.min(1, c * (1 - k) + k); - g = 1 - Math.min(1, m * (1 - k) + k); - b = 1 - Math.min(1, y * (1 - k) + k); - - return [r * 255, g * 255, b * 255]; -}; - -convert.xyz.rgb = function (xyz) { - var x = xyz[0] / 100; - var y = xyz[1] / 100; - var z = xyz[2] / 100; - var r; - var g; - var b; - - r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); - g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); - b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - - // assume sRGB - r = r > 0.0031308 - ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) - : r * 12.92; - - g = g > 0.0031308 - ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) - : g * 12.92; - - b = b > 0.0031308 - ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) - : b * 12.92; - - r = Math.min(Math.max(0, r), 1); - g = Math.min(Math.max(0, g), 1); - b = Math.min(Math.max(0, b), 1); - - return [r * 255, g * 255, b * 255]; -}; - -convert.xyz.lab = function (xyz) { - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; -}; - -convert.lab.xyz = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var x; - var y; - var z; - - y = (l + 16) / 116; - x = a / 500 + y; - z = y - b / 200; - - var y2 = Math.pow(y, 3); - var x2 = Math.pow(x, 3); - var z2 = Math.pow(z, 3); - y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; - x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; - z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; - - x *= 95.047; - y *= 100; - z *= 108.883; - - return [x, y, z]; -}; - -convert.lab.lch = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var hr; - var h; - var c; - - hr = Math.atan2(b, a); - h = hr * 360 / 2 / Math.PI; - - if (h < 0) { - h += 360; - } - - c = Math.sqrt(a * a + b * b); - - return [l, c, h]; -}; - -convert.lch.lab = function (lch) { - var l = lch[0]; - var c = lch[1]; - var h = lch[2]; - var a; - var b; - var hr; - - hr = h / 360 * 2 * Math.PI; - a = c * Math.cos(hr); - b = c * Math.sin(hr); - - return [l, a, b]; -}; - -convert.rgb.ansi16 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; - var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization - - value = Math.round(value / 50); - - if (value === 0) { - return 30; - } - - var ansi = 30 - + ((Math.round(b / 255) << 2) - | (Math.round(g / 255) << 1) - | Math.round(r / 255)); - - if (value === 2) { - ansi += 60; - } - - return ansi; -}; - -convert.hsv.ansi16 = function (args) { - // optimization here; we already know the value and don't need to get - // it converted for us. - return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); -}; - -convert.rgb.ansi256 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; - - // we use the extended greyscale palette here, with the exception of - // black and white. normal palette only has 4 greyscale shades. - if (r === g && g === b) { - if (r < 8) { - return 16; - } - - if (r > 248) { - return 231; - } - - return Math.round(((r - 8) / 247) * 24) + 232; - } - - var ansi = 16 - + (36 * Math.round(r / 255 * 5)) - + (6 * Math.round(g / 255 * 5)) - + Math.round(b / 255 * 5); - - return ansi; -}; - -convert.ansi16.rgb = function (args) { - var color = args % 10; - - // handle greyscale - if (color === 0 || color === 7) { - if (args > 50) { - color += 3.5; - } - - color = color / 10.5 * 255; - - return [color, color, color]; - } - - var mult = (~~(args > 50) + 1) * 0.5; - var r = ((color & 1) * mult) * 255; - var g = (((color >> 1) & 1) * mult) * 255; - var b = (((color >> 2) & 1) * mult) * 255; - - return [r, g, b]; -}; - -convert.ansi256.rgb = function (args) { - // handle greyscale - if (args >= 232) { - var c = (args - 232) * 10 + 8; - return [c, c, c]; - } - - args -= 16; - - var rem; - var r = Math.floor(args / 36) / 5 * 255; - var g = Math.floor((rem = args % 36) / 6) / 5 * 255; - var b = (rem % 6) / 5 * 255; - - return [r, g, b]; -}; - -convert.rgb.hex = function (args) { - var integer = ((Math.round(args[0]) & 0xFF) << 16) - + ((Math.round(args[1]) & 0xFF) << 8) - + (Math.round(args[2]) & 0xFF); - - var string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; - -convert.hex.rgb = function (args) { - var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); - if (!match) { - return [0, 0, 0]; - } - - var colorString = match[0]; - - if (match[0].length === 3) { - colorString = colorString.split('').map(function (char) { - return char + char; - }).join(''); - } - - var integer = parseInt(colorString, 16); - var r = (integer >> 16) & 0xFF; - var g = (integer >> 8) & 0xFF; - var b = integer & 0xFF; - - return [r, g, b]; -}; - -convert.rgb.hcg = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var max = Math.max(Math.max(r, g), b); - var min = Math.min(Math.min(r, g), b); - var chroma = (max - min); - var grayscale; - var hue; - - if (chroma < 1) { - grayscale = min / (1 - chroma); - } else { - grayscale = 0; - } - - if (chroma <= 0) { - hue = 0; - } else - if (max === r) { - hue = ((g - b) / chroma) % 6; - } else - if (max === g) { - hue = 2 + (b - r) / chroma; - } else { - hue = 4 + (r - g) / chroma + 4; - } - - hue /= 6; - hue %= 1; - - return [hue * 360, chroma * 100, grayscale * 100]; -}; - -convert.hsl.hcg = function (hsl) { - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var c = 1; - var f = 0; - - if (l < 0.5) { - c = 2.0 * s * l; - } else { - c = 2.0 * s * (1.0 - l); - } - - if (c < 1.0) { - f = (l - 0.5 * c) / (1.0 - c); - } - - return [hsl[0], c * 100, f * 100]; -}; - -convert.hsv.hcg = function (hsv) { - var s = hsv[1] / 100; - var v = hsv[2] / 100; - - var c = s * v; - var f = 0; - - if (c < 1.0) { - f = (v - c) / (1 - c); - } - - return [hsv[0], c * 100, f * 100]; -}; - -convert.hcg.rgb = function (hcg) { - var h = hcg[0] / 360; - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - if (c === 0.0) { - return [g * 255, g * 255, g * 255]; - } - - var pure = [0, 0, 0]; - var hi = (h % 1) * 6; - var v = hi % 1; - var w = 1 - v; - var mg = 0; - - switch (Math.floor(hi)) { - case 0: - pure[0] = 1; pure[1] = v; pure[2] = 0; break; - case 1: - pure[0] = w; pure[1] = 1; pure[2] = 0; break; - case 2: - pure[0] = 0; pure[1] = 1; pure[2] = v; break; - case 3: - pure[0] = 0; pure[1] = w; pure[2] = 1; break; - case 4: - pure[0] = v; pure[1] = 0; pure[2] = 1; break; - default: - pure[0] = 1; pure[1] = 0; pure[2] = w; - } - - mg = (1.0 - c) * g; - - return [ - (c * pure[0] + mg) * 255, - (c * pure[1] + mg) * 255, - (c * pure[2] + mg) * 255 - ]; -}; - -convert.hcg.hsv = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - var v = c + g * (1.0 - c); - var f = 0; - - if (v > 0.0) { - f = c / v; - } - - return [hcg[0], f * 100, v * 100]; -}; - -convert.hcg.hsl = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - var l = g * (1.0 - c) + 0.5 * c; - var s = 0; - - if (l > 0.0 && l < 0.5) { - s = c / (2 * l); - } else - if (l >= 0.5 && l < 1.0) { - s = c / (2 * (1 - l)); - } - - return [hcg[0], s * 100, l * 100]; -}; - -convert.hcg.hwb = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - var v = c + g * (1.0 - c); - return [hcg[0], (v - c) * 100, (1 - v) * 100]; -}; - -convert.hwb.hcg = function (hwb) { - var w = hwb[1] / 100; - var b = hwb[2] / 100; - var v = 1 - b; - var c = v - w; - var g = 0; - - if (c < 1) { - g = (v - c) / (1 - c); - } - - return [hwb[0], c * 100, g * 100]; -}; - -convert.apple.rgb = function (apple) { - return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; -}; - -convert.rgb.apple = function (rgb) { - return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; -}; - -convert.gray.rgb = function (args) { - return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; -}; - -convert.gray.hsl = convert.gray.hsv = function (args) { - return [0, 0, args[0]]; -}; - -convert.gray.hwb = function (gray) { - return [0, 100, gray[0]]; -}; - -convert.gray.cmyk = function (gray) { - return [0, 0, 0, gray[0]]; -}; - -convert.gray.lab = function (gray) { - return [gray[0], 0, 0]; -}; - -convert.gray.hex = function (gray) { - var val = Math.round(gray[0] / 100 * 255) & 0xFF; - var integer = (val << 16) + (val << 8) + val; - - var string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; - -convert.rgb.gray = function (rgb) { - var val = (rgb[0] + rgb[1] + rgb[2]) / 3; - return [val / 255 * 100]; -}; - - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var _Colorpicker = __webpack_require__(8); - -var _Colorpicker2 = _interopRequireDefault(_Colorpicker); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var plugin = 'colorpicker'; - -_jquery2.default[plugin] = _Colorpicker2.default; - -// Colorpicker jQuery Plugin API -_jquery2.default.fn[plugin] = function (option) { - var fnArgs = Array.prototype.slice.call(arguments, 1), - isSingleElement = this.length === 1, - returnValue = null; - - var $elements = this.each(function () { - var $this = (0, _jquery2.default)(this), - inst = $this.data(plugin), - options = (typeof option === 'undefined' ? 'undefined' : _typeof(option)) === 'object' ? option : {}; - - // Create instance if does not exist - if (!inst) { - inst = new _Colorpicker2.default(this, options); - $this.data(plugin, inst); - } - - if (!isSingleElement) { - return; - } - - returnValue = $this; - - if (typeof option === 'string') { - if (option === 'colorpicker') { - // Return colorpicker instance: e.g. .colorpicker('colorpicker') - returnValue = inst; - } else if (_jquery2.default.isFunction(inst[option])) { - // Return method call return value: e.g. .colorpicker('isEnabled') - returnValue = inst[option].apply(inst, fnArgs); - } else { - // Return property value: e.g. .colorpicker('element') - returnValue = inst[option]; - } - } - }); - - return isSingleElement ? returnValue : $elements; -}; - -_jquery2.default.fn[plugin].constructor = _Colorpicker2.default; - -/***/ }), -/* 8 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _Extension = __webpack_require__(1); - -var _Extension2 = _interopRequireDefault(_Extension); - -var _options = __webpack_require__(3); - -var _options2 = _interopRequireDefault(_options); - -var _extensions = __webpack_require__(9); - -var _extensions2 = _interopRequireDefault(_extensions); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _SliderHandler = __webpack_require__(13); - -var _SliderHandler2 = _interopRequireDefault(_SliderHandler); - -var _PopupHandler = __webpack_require__(14); - -var _PopupHandler2 = _interopRequireDefault(_PopupHandler); - -var _InputHandler = __webpack_require__(15); - -var _InputHandler2 = _interopRequireDefault(_InputHandler); - -var _ColorHandler = __webpack_require__(22); - -var _ColorHandler2 = _interopRequireDefault(_ColorHandler); - -var _PickerHandler = __webpack_require__(23); - -var _PickerHandler2 = _interopRequireDefault(_PickerHandler); - -var _AddonHandler = __webpack_require__(24); - -var _AddonHandler2 = _interopRequireDefault(_AddonHandler); - -var _ColorItem = __webpack_require__(2); - -var _ColorItem2 = _interopRequireDefault(_ColorItem); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var colorPickerIdCounter = 0; - -var root = typeof self !== 'undefined' ? self : undefined; // window - -/** - * Colorpicker widget class - */ - -var Colorpicker = function () { - _createClass(Colorpicker, [{ - key: 'color', - - - /** - * Internal color object - * - * @type {Color|null} - */ - get: function get() { - return this.colorHandler.color; - } - - /** - * Internal color format - * - * @type {String|null} - */ - - }, { - key: 'format', - get: function get() { - return this.colorHandler.format; - } - - /** - * Getter of the picker element - * - * @returns {jQuery|HTMLElement} - */ - - }, { - key: 'picker', - get: function get() { - return this.pickerHandler.picker; - } - - /** - * @fires Colorpicker#colorpickerCreate - * @param {Object|String} element - * @param {Object} options - * @constructor - */ - - }], [{ - key: 'Color', - - /** - * Color class - * - * @static - * @type {Color} - */ - get: function get() { - return _ColorItem2.default; - } - - /** - * Extension class - * - * @static - * @type {Extension} - */ - - }, { - key: 'Extension', - get: function get() { - return _Extension2.default; - } - }]); - - function Colorpicker(element, options) { - _classCallCheck(this, Colorpicker); - - colorPickerIdCounter += 1; - /** - * The colorpicker instance number - * @type {number} - */ - this.id = colorPickerIdCounter; - - /** - * Latest colorpicker event - * - * @type {{name: String, e: *}} - */ - this.lastEvent = { - alias: null, - e: null - }; - - /** - * The element that the colorpicker is bound to - * - * @type {*|jQuery} - */ - this.element = (0, _jquery2.default)(element).addClass('colorpicker-element').attr('data-colorpicker-id', this.id); - - /** - * @type {defaults} - */ - this.options = _jquery2.default.extend(true, {}, _options2.default, options, this.element.data()); - - /** - * @type {boolean} - * @private - */ - this.disabled = false; - - /** - * Extensions added to this instance - * - * @type {Extension[]} - */ - this.extensions = []; - - /** - * The element where the - * @type {*|jQuery} - */ - this.container = this.options.container === true || this.options.container !== true && this.options.inline === true ? this.element : this.options.container; - - this.container = this.container !== false ? (0, _jquery2.default)(this.container) : false; - - /** - * @type {InputHandler} - */ - this.inputHandler = new _InputHandler2.default(this); - /** - * @type {ColorHandler} - */ - this.colorHandler = new _ColorHandler2.default(this); - /** - * @type {SliderHandler} - */ - this.sliderHandler = new _SliderHandler2.default(this); - /** - * @type {PopupHandler} - */ - this.popupHandler = new _PopupHandler2.default(this, root); - /** - * @type {PickerHandler} - */ - this.pickerHandler = new _PickerHandler2.default(this); - /** - * @type {AddonHandler} - */ - this.addonHandler = new _AddonHandler2.default(this); - - this.init(); - - // Emit a create event - (0, _jquery2.default)(_jquery2.default.proxy(function () { - /** - * (Colorpicker) When the Colorpicker instance has been created and the DOM is ready. - * - * @event Colorpicker#colorpickerCreate - */ - this.trigger('colorpickerCreate'); - }, this)); - } - - /** - * Initializes the plugin - * @private - */ - - - _createClass(Colorpicker, [{ - key: 'init', - value: function init() { - // Init addon - this.addonHandler.bind(); - - // Init input - this.inputHandler.bind(); - - // Init extensions (before initializing the color) - this.initExtensions(); - - // Init color - this.colorHandler.bind(); - - // Init picker - this.pickerHandler.bind(); - - // Init sliders and popup - this.sliderHandler.bind(); - this.popupHandler.bind(); - - // Inject into the DOM (this may make it visible) - this.pickerHandler.attach(); - - // Update all components - this.update(); - - if (this.inputHandler.isDisabled()) { - this.disable(); - } - } - - /** - * Initializes the plugin extensions - * @private - */ - - }, { - key: 'initExtensions', - value: function initExtensions() { - var _this = this; - - if (!Array.isArray(this.options.extensions)) { - this.options.extensions = []; - } - - if (this.options.debug) { - this.options.extensions.push({ name: 'debugger' }); - } - - // Register and instantiate extensions - this.options.extensions.forEach(function (ext) { - _this.registerExtension(Colorpicker.extensions[ext.name.toLowerCase()], ext.options || {}); - }); - } - - /** - * Creates and registers the given extension - * - * @param {Extension} ExtensionClass The extension class to instantiate - * @param {Object} [config] Extension configuration - * @returns {Extension} - */ - - }, { - key: 'registerExtension', - value: function registerExtension(ExtensionClass) { - var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - var ext = new ExtensionClass(this, config); - - this.extensions.push(ext); - return ext; - } - - /** - * Destroys the current instance - * - * @fires Colorpicker#colorpickerDestroy - */ - - }, { - key: 'destroy', - value: function destroy() { - var color = this.color; - - this.sliderHandler.unbind(); - this.inputHandler.unbind(); - this.popupHandler.unbind(); - this.colorHandler.unbind(); - this.addonHandler.unbind(); - this.pickerHandler.unbind(); - - this.element.removeClass('colorpicker-element').removeData('colorpicker', 'color').off('.colorpicker'); - - /** - * (Colorpicker) When the instance is destroyed with all events unbound. - * - * @event Colorpicker#colorpickerDestroy - */ - this.trigger('colorpickerDestroy', color); - } - - /** - * Shows the colorpicker widget if hidden. - * If the colorpicker is disabled this call will be ignored. - * - * @fires Colorpicker#colorpickerShow - * @param {Event} [e] - */ - - }, { - key: 'show', - value: function show(e) { - this.popupHandler.show(e); - } - - /** - * Hides the colorpicker widget. - * - * @fires Colorpicker#colorpickerHide - * @param {Event} [e] - */ - - }, { - key: 'hide', - value: function hide(e) { - this.popupHandler.hide(e); - } - - /** - * Toggles the colorpicker between visible and hidden. - * - * @fires Colorpicker#colorpickerShow - * @fires Colorpicker#colorpickerHide - * @param {Event} [e] - */ - - }, { - key: 'toggle', - value: function toggle(e) { - this.popupHandler.toggle(e); - } - - /** - * Returns the current color value as string - * - * @param {String|*} [defaultValue] - * @returns {String|*} - */ - - }, { - key: 'getValue', - value: function getValue() { - var defaultValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - - var val = this.colorHandler.color; - - val = val instanceof _ColorItem2.default ? val : defaultValue; - - if (val instanceof _ColorItem2.default) { - return val.string(this.format); - } - - return val; - } - - /** - * Sets the color manually - * - * @fires Colorpicker#colorpickerChange - * @param {String|Color} val - */ - - }, { - key: 'setValue', - value: function setValue(val) { - if (this.isDisabled()) { - return; - } - var ch = this.colorHandler; - - if (ch.hasColor() && !!val && ch.color.equals(val) || !ch.hasColor() && !val) { - // same color or still empty - return; - } - - ch.color = val ? ch.createColor(val, this.options.autoInputFallback) : null; - - /** - * (Colorpicker) When the color is set programmatically with setValue(). - * - * @event Colorpicker#colorpickerChange - */ - this.trigger('colorpickerChange', ch.color, val); - - // force update if color has changed to empty - this.update(); - } - - /** - * Updates the UI and the input color according to the internal color. - * - * @fires Colorpicker#colorpickerUpdate - */ - - }, { - key: 'update', - value: function update() { - if (this.colorHandler.hasColor()) { - this.inputHandler.update(); - } else { - this.colorHandler.assureColor(); - } - - this.addonHandler.update(); - this.pickerHandler.update(); - - /** - * (Colorpicker) Fired when the widget is updated. - * - * @event Colorpicker#colorpickerUpdate - */ - this.trigger('colorpickerUpdate'); - } - - /** - * Enables the widget and the input if any - * - * @fires Colorpicker#colorpickerEnable - * @returns {boolean} - */ - - }, { - key: 'enable', - value: function enable() { - this.inputHandler.enable(); - this.disabled = false; - this.picker.removeClass('colorpicker-disabled'); - - /** - * (Colorpicker) When the widget has been enabled. - * - * @event Colorpicker#colorpickerEnable - */ - this.trigger('colorpickerEnable'); - return true; - } - - /** - * Disables the widget and the input if any - * - * @fires Colorpicker#colorpickerDisable - * @returns {boolean} - */ - - }, { - key: 'disable', - value: function disable() { - this.inputHandler.disable(); - this.disabled = true; - this.picker.addClass('colorpicker-disabled'); - - /** - * (Colorpicker) When the widget has been disabled. - * - * @event Colorpicker#colorpickerDisable - */ - this.trigger('colorpickerDisable'); - return true; - } - - /** - * Returns true if this instance is enabled - * @returns {boolean} - */ - - }, { - key: 'isEnabled', - value: function isEnabled() { - return !this.isDisabled(); - } - - /** - * Returns true if this instance is disabled - * @returns {boolean} - */ - - }, { - key: 'isDisabled', - value: function isDisabled() { - return this.disabled === true; - } - - /** - * Triggers a Colorpicker event. - * - * @param eventName - * @param color - * @param value - */ - - }, { - key: 'trigger', - value: function trigger(eventName) { - var color = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - - this.element.trigger({ - type: eventName, - colorpicker: this, - color: color ? color : this.color, - value: value ? value : this.getValue() - }); - } - }]); - - return Colorpicker; -}(); - -/** - * Colorpicker extension classes, indexed by extension name - * - * @static - * @type {Object} a map between the extension name and its class - */ - - -Colorpicker.extensions = _extensions2.default; - -exports.default = Colorpicker; -module.exports = exports.default; - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Palette = exports.Swatches = exports.Preview = exports.Debugger = undefined; - -var _Debugger = __webpack_require__(10); - -var _Debugger2 = _interopRequireDefault(_Debugger); - -var _Preview = __webpack_require__(11); - -var _Preview2 = _interopRequireDefault(_Preview); - -var _Swatches = __webpack_require__(12); - -var _Swatches2 = _interopRequireDefault(_Swatches); - -var _Palette = __webpack_require__(4); - -var _Palette2 = _interopRequireDefault(_Palette); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.Debugger = _Debugger2.default; -exports.Preview = _Preview2.default; -exports.Swatches = _Swatches2.default; -exports.Palette = _Palette2.default; -exports.default = { - 'debugger': _Debugger2.default, - 'preview': _Preview2.default, - 'swatches': _Swatches2.default, - 'palette': _Palette2.default -}; - -/***/ }), -/* 10 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _Extension2 = __webpack_require__(1); - -var _Extension3 = _interopRequireDefault(_Extension2); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/** - * Debugger extension class - * @alias DebuggerExtension - * @ignore - */ -var Debugger = function (_Extension) { - _inherits(Debugger, _Extension); - - function Debugger(colorpicker) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, Debugger); - - /** - * @type {number} - */ - var _this = _possibleConstructorReturn(this, (Debugger.__proto__ || Object.getPrototypeOf(Debugger)).call(this, colorpicker, options)); - - _this.eventCounter = 0; - if (_this.colorpicker.inputHandler.hasInput()) { - _this.colorpicker.inputHandler.input.on('change.colorpicker-ext', _jquery2.default.proxy(_this.onChangeInput, _this)); - } - return _this; - } - - /** - * @fires DebuggerExtension#colorpickerDebug - * @param {string} eventName - * @param {*} args - */ - - - _createClass(Debugger, [{ - key: 'log', - value: function log(eventName) { - var _console; - - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - this.eventCounter += 1; - - var logMessage = '#' + this.eventCounter + ': Colorpicker#' + this.colorpicker.id + ' [' + eventName + ']'; - - (_console = console).debug.apply(_console, [logMessage].concat(args)); - - /** - * Whenever the debugger logs an event, this other event is emitted. - * - * @event DebuggerExtension#colorpickerDebug - * @type {object} The event object - * @property {Colorpicker} colorpicker The Colorpicker instance - * @property {ColorItem} color The color instance - * @property {{debugger: DebuggerExtension, eventName: String, logArgs: Array, logMessage: String}} debug - * The debug info - */ - this.colorpicker.element.trigger({ - type: 'colorpickerDebug', - colorpicker: this.colorpicker, - color: this.color, - value: null, - debug: { - debugger: this, - eventName: eventName, - logArgs: args, - logMessage: logMessage - } - }); - } - }, { - key: 'resolveColor', - value: function resolveColor(color) { - var realColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - this.log('resolveColor()', color, realColor); - return false; - } - }, { - key: 'onCreate', - value: function onCreate(event) { - this.log('colorpickerCreate'); - return _get(Debugger.prototype.__proto__ || Object.getPrototypeOf(Debugger.prototype), 'onCreate', this).call(this, event); - } - }, { - key: 'onDestroy', - value: function onDestroy(event) { - this.log('colorpickerDestroy'); - this.eventCounter = 0; - - if (this.colorpicker.inputHandler.hasInput()) { - this.colorpicker.inputHandler.input.off('.colorpicker-ext'); - } - - return _get(Debugger.prototype.__proto__ || Object.getPrototypeOf(Debugger.prototype), 'onDestroy', this).call(this, event); - } - }, { - key: 'onUpdate', - value: function onUpdate(event) { - this.log('colorpickerUpdate'); - } - - /** - * @listens Colorpicker#change - * @param {Event} event - */ - - }, { - key: 'onChangeInput', - value: function onChangeInput(event) { - this.log('input:change.colorpicker', event.value, event.color); - } - }, { - key: 'onChange', - value: function onChange(event) { - this.log('colorpickerChange', event.value, event.color); - } - }, { - key: 'onInvalid', - value: function onInvalid(event) { - this.log('colorpickerInvalid', event.value, event.color); - } - }, { - key: 'onHide', - value: function onHide(event) { - this.log('colorpickerHide'); - this.eventCounter = 0; - } - }, { - key: 'onShow', - value: function onShow(event) { - this.log('colorpickerShow'); - } - }, { - key: 'onDisable', - value: function onDisable(event) { - this.log('colorpickerDisable'); - } - }, { - key: 'onEnable', - value: function onEnable(event) { - this.log('colorpickerEnable'); - } - }]); - - return Debugger; -}(_Extension3.default); - -exports.default = Debugger; -module.exports = exports.default; - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _Extension2 = __webpack_require__(1); - -var _Extension3 = _interopRequireDefault(_Extension2); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/** - * Color preview extension - * @ignore - */ -var Preview = function (_Extension) { - _inherits(Preview, _Extension); - - function Preview(colorpicker) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, Preview); - - var _this = _possibleConstructorReturn(this, (Preview.__proto__ || Object.getPrototypeOf(Preview)).call(this, colorpicker, _jquery2.default.extend(true, {}, { - template: '
', - showText: true, - format: colorpicker.format - }, options))); - - _this.element = (0, _jquery2.default)(_this.options.template); - _this.elementInner = _this.element.find('div'); - return _this; - } - - _createClass(Preview, [{ - key: 'onCreate', - value: function onCreate(event) { - _get(Preview.prototype.__proto__ || Object.getPrototypeOf(Preview.prototype), 'onCreate', this).call(this, event); - this.colorpicker.picker.append(this.element); - } - }, { - key: 'onUpdate', - value: function onUpdate(event) { - _get(Preview.prototype.__proto__ || Object.getPrototypeOf(Preview.prototype), 'onUpdate', this).call(this, event); - - if (!event.color) { - this.elementInner.css('backgroundColor', null).css('color', null).html(''); - return; - } - - this.elementInner.css('backgroundColor', event.color.toRgbString()); - - if (this.options.showText) { - this.elementInner.html(event.color.string(this.options.format || this.colorpicker.format)); - - if (event.color.isDark() && event.color.alpha > 0.5) { - this.elementInner.css('color', 'white'); - } else { - this.elementInner.css('color', 'black'); - } - } - } - }]); - - return Preview; -}(_Extension3.default); - -exports.default = Preview; -module.exports = exports.default; - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _Palette2 = __webpack_require__(4); - -var _Palette3 = _interopRequireDefault(_Palette2); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var defaults = { - barTemplate: '
\n
\n
', - swatchTemplate: '' -}; - -/** - * Color swatches extension - * @ignore - */ - -var Swatches = function (_Palette) { - _inherits(Swatches, _Palette); - - function Swatches(colorpicker) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, Swatches); - - var _this = _possibleConstructorReturn(this, (Swatches.__proto__ || Object.getPrototypeOf(Swatches)).call(this, colorpicker, _jquery2.default.extend(true, {}, defaults, options))); - - _this.element = null; - return _this; - } - - _createClass(Swatches, [{ - key: 'isEnabled', - value: function isEnabled() { - return this.getLength() > 0; - } - }, { - key: 'onCreate', - value: function onCreate(event) { - _get(Swatches.prototype.__proto__ || Object.getPrototypeOf(Swatches.prototype), 'onCreate', this).call(this, event); - - if (!this.isEnabled()) { - return; - } - - this.element = (0, _jquery2.default)(this.options.barTemplate); - this.load(); - this.colorpicker.picker.append(this.element); - } - }, { - key: 'load', - value: function load() { - var _this2 = this; - - var colorpicker = this.colorpicker, - swatchContainer = this.element.find('.colorpicker-swatches--inner'), - isAliased = this.options.namesAsValues === true && !Array.isArray(this.colors); - - swatchContainer.empty(); - - _jquery2.default.each(this.colors, function (name, value) { - var $swatch = (0, _jquery2.default)(_this2.options.swatchTemplate).attr('data-name', name).attr('data-value', value).attr('title', isAliased ? name + ': ' + value : value).on('mousedown.colorpicker touchstart.colorpicker', function (e) { - var $sw = (0, _jquery2.default)(this); - - // e.preventDefault(); - - colorpicker.setValue(isAliased ? $sw.attr('data-name') : $sw.attr('data-value')); - }); - - $swatch.find('.colorpicker-swatch--inner').css('background-color', value); - - swatchContainer.append($swatch); - }); - - swatchContainer.append((0, _jquery2.default)('')); - } - }]); - - return Swatches; -}(_Palette3.default); - -exports.default = Swatches; -module.exports = exports.default; - -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Class that handles all configured sliders on mouse or touch events. - * @ignore - */ -var SliderHandler = function () { - /** - * @param {Colorpicker} colorpicker - */ - function SliderHandler(colorpicker) { - _classCallCheck(this, SliderHandler); - - /** - * @type {Colorpicker} - */ - this.colorpicker = colorpicker; - /** - * @type {*|String} - * @private - */ - this.currentSlider = null; - /** - * @type {{left: number, top: number}} - * @private - */ - this.mousePointer = { - left: 0, - top: 0 - }; - - /** - * @type {Function} - */ - this.onMove = _jquery2.default.proxy(this.defaultOnMove, this); - } - - /** - * This function is called every time a slider guide is moved - * The scope of "this" is the SliderHandler object. - * - * @param {int} top - * @param {int} left - */ - - - _createClass(SliderHandler, [{ - key: 'defaultOnMove', - value: function defaultOnMove(top, left) { - if (!this.currentSlider) { - return; - } - - var slider = this.currentSlider, - cp = this.colorpicker, - ch = cp.colorHandler; - - // Create a color object - var color = !ch.hasColor() ? ch.getFallbackColor() : ch.color.getClone(); - - // Adjust the guide position - slider.guideStyle.left = left + 'px'; - slider.guideStyle.top = top + 'px'; - - // Adjust the color - if (slider.callLeft) { - color[slider.callLeft](left / slider.maxLeft); - } - if (slider.callTop) { - color[slider.callTop](top / slider.maxTop); - } - - // Set the new color - cp.setValue(color); - cp.popupHandler.focus(); - } - - /** - * Binds the colorpicker sliders to the mouse/touch events - */ - - }, { - key: 'bind', - value: function bind() { - var sliders = this.colorpicker.options.horizontal ? this.colorpicker.options.slidersHorz : this.colorpicker.options.sliders; - - var sliderClasses = []; - - for (var sliderName in sliders) { - if (!sliders.hasOwnProperty(sliderName)) { - continue; - } - - sliderClasses.push(sliders[sliderName].selector); - } - - this.colorpicker.picker.find(sliderClasses.join(', ')).on('mousedown.colorpicker touchstart.colorpicker', _jquery2.default.proxy(this.pressed, this)); - } - - /** - * Unbinds any event bound by this handler - */ - - }, { - key: 'unbind', - value: function unbind() { - (0, _jquery2.default)(this.colorpicker.picker).off({ - 'mousemove.colorpicker': _jquery2.default.proxy(this.moved, this), - 'touchmove.colorpicker': _jquery2.default.proxy(this.moved, this), - 'mouseup.colorpicker': _jquery2.default.proxy(this.released, this), - 'touchend.colorpicker': _jquery2.default.proxy(this.released, this) - }); - } - - /** - * Function triggered when clicking in one of the color adjustment bars - * - * @private - * @fires Colorpicker#mousemove - * @param {Event} e - */ - - }, { - key: 'pressed', - value: function pressed(e) { - if (this.colorpicker.isDisabled()) { - return; - } - this.colorpicker.lastEvent.alias = 'pressed'; - this.colorpicker.lastEvent.e = e; - - if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) { - e.pageX = e.originalEvent.touches[0].pageX; - e.pageY = e.originalEvent.touches[0].pageY; - } - // e.stopPropagation(); - // e.preventDefault(); - - var target = (0, _jquery2.default)(e.target); - - // detect the slider and set the limits and callbacks - var zone = target.closest('div'); - - var sliders = this.colorpicker.options.horizontal ? this.colorpicker.options.slidersHorz : this.colorpicker.options.sliders; - - if (zone.is('.colorpicker')) { - return; - } - - this.currentSlider = null; - - for (var sliderName in sliders) { - if (!sliders.hasOwnProperty(sliderName)) { - continue; - } - - var slider = sliders[sliderName]; - - if (zone.is(slider.selector)) { - this.currentSlider = _jquery2.default.extend({}, slider, { name: sliderName }); - break; - } else if (slider.childSelector !== undefined && zone.is(slider.childSelector)) { - this.currentSlider = _jquery2.default.extend({}, slider, { name: sliderName }); - zone = zone.parent(); // zone.parents(slider.selector).first() ? - break; - } - } - - var guide = zone.find('.colorpicker-guide').get(0); - - if (this.currentSlider === null || guide === null) { - return; - } - - var offset = zone.offset(); - - // reference to guide's style - this.currentSlider.guideStyle = guide.style; - this.currentSlider.left = e.pageX - offset.left; - this.currentSlider.top = e.pageY - offset.top; - this.mousePointer = { - left: e.pageX, - top: e.pageY - }; - - // TODO: fix moving outside the picker makes the guides to keep moving. The event needs to be bound to the window. - /** - * (window.document) Triggered on mousedown for the document object, - * so the color adjustment guide is moved to the clicked position. - * - * @event Colorpicker#mousemove - */ - (0, _jquery2.default)(this.colorpicker.picker).on({ - 'mousemove.colorpicker': _jquery2.default.proxy(this.moved, this), - 'touchmove.colorpicker': _jquery2.default.proxy(this.moved, this), - 'mouseup.colorpicker': _jquery2.default.proxy(this.released, this), - 'touchend.colorpicker': _jquery2.default.proxy(this.released, this) - }).trigger('mousemove'); - } - - /** - * Function triggered when dragging a guide inside one of the color adjustment bars. - * - * @private - * @param {Event} e - */ - - }, { - key: 'moved', - value: function moved(e) { - this.colorpicker.lastEvent.alias = 'moved'; - this.colorpicker.lastEvent.e = e; - - if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) { - e.pageX = e.originalEvent.touches[0].pageX; - e.pageY = e.originalEvent.touches[0].pageY; - } - - // e.stopPropagation(); - e.preventDefault(); // prevents scrolling on mobile - - var left = Math.max(0, Math.min(this.currentSlider.maxLeft, this.currentSlider.left + ((e.pageX || this.mousePointer.left) - this.mousePointer.left))); - - var top = Math.max(0, Math.min(this.currentSlider.maxTop, this.currentSlider.top + ((e.pageY || this.mousePointer.top) - this.mousePointer.top))); - - this.onMove(top, left); - } - - /** - * Function triggered when releasing the click in one of the color adjustment bars. - * - * @private - * @param {Event} e - */ - - }, { - key: 'released', - value: function released(e) { - this.colorpicker.lastEvent.alias = 'released'; - this.colorpicker.lastEvent.e = e; - - // e.stopPropagation(); - // e.preventDefault(); - - (0, _jquery2.default)(this.colorpicker.picker).off({ - 'mousemove.colorpicker': this.moved, - 'touchmove.colorpicker': this.moved, - 'mouseup.colorpicker': this.released, - 'touchend.colorpicker': this.released - }); - } - }]); - - return SliderHandler; -}(); - -exports.default = SliderHandler; -module.exports = exports.default; - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _options = __webpack_require__(3); - -var _options2 = _interopRequireDefault(_options); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Handles everything related to the UI of the colorpicker popup: show, hide, position,... - * @ignore - */ -var PopupHandler = function () { - /** - * @param {Colorpicker} colorpicker - * @param {Window} root - */ - function PopupHandler(colorpicker, root) { - _classCallCheck(this, PopupHandler); - - /** - * @type {Window} - */ - this.root = root; - /** - * @type {Colorpicker} - */ - this.colorpicker = colorpicker; - /** - * @type {jQuery} - */ - this.popoverTarget = null; - /** - * @type {jQuery} - */ - this.popoverTip = null; - - /** - * If true, the latest click was inside the popover - * @type {boolean} - */ - this.clicking = false; - /** - * @type {boolean} - */ - this.hidding = false; - /** - * @type {boolean} - */ - this.showing = false; - } - - /** - * @private - * @returns {jQuery|false} - */ - - - _createClass(PopupHandler, [{ - key: 'bind', - - - /** - * Binds the different colorpicker elements to the focus/mouse/touch events so it reacts in order to show or - * hide the colorpicker popup accordingly. It also adds the proper classes. - */ - value: function bind() { - var cp = this.colorpicker; - - if (cp.options.inline) { - cp.picker.addClass('colorpicker-inline colorpicker-visible'); - return; // no need to bind show/hide events for inline elements - } - - cp.picker.addClass('colorpicker-popup colorpicker-hidden'); - - // there is no input or addon - if (!this.hasInput && !this.hasAddon) { - return; - } - - // create Bootstrap 4 popover - if (cp.options.popover) { - this.createPopover(); - } - - // bind addon show/hide events - if (this.hasAddon) { - // enable focus on addons - if (!this.addon.attr('tabindex')) { - this.addon.attr('tabindex', 0); - } - - this.addon.on({ - 'mousedown.colorpicker touchstart.colorpicker': _jquery2.default.proxy(this.toggle, this) - }); - - this.addon.on({ - 'focus.colorpicker': _jquery2.default.proxy(this.show, this) - }); - - this.addon.on({ - 'focusout.colorpicker': _jquery2.default.proxy(this.hide, this) - }); - } - - // bind input show/hide events - if (this.hasInput && !this.hasAddon) { - this.input.on({ - 'mousedown.colorpicker touchstart.colorpicker': _jquery2.default.proxy(this.show, this), - 'focus.colorpicker': _jquery2.default.proxy(this.show, this) - }); - - this.input.on({ - 'focusout.colorpicker': _jquery2.default.proxy(this.hide, this) - }); - } - - // reposition popup on window resize - (0, _jquery2.default)(this.root).on('resize.colorpicker', _jquery2.default.proxy(this.reposition, this)); - } - - /** - * Unbinds any event bound by this handler - */ - - }, { - key: 'unbind', - value: function unbind() { - if (this.hasInput) { - this.input.off({ - 'mousedown.colorpicker touchstart.colorpicker': _jquery2.default.proxy(this.show, this), - 'focus.colorpicker': _jquery2.default.proxy(this.show, this) - }); - this.input.off({ - 'focusout.colorpicker': _jquery2.default.proxy(this.hide, this) - }); - } - - if (this.hasAddon) { - this.addon.off({ - 'mousedown.colorpicker touchstart.colorpicker': _jquery2.default.proxy(this.toggle, this) - }); - this.addon.off({ - 'focus.colorpicker': _jquery2.default.proxy(this.show, this) - }); - this.addon.off({ - 'focusout.colorpicker': _jquery2.default.proxy(this.hide, this) - }); - } - - if (this.popoverTarget) { - this.popoverTarget.popover('dispose'); - } - - (0, _jquery2.default)(this.root).off('resize.colorpicker', _jquery2.default.proxy(this.reposition, this)); - (0, _jquery2.default)(this.root.document).off('mousedown.colorpicker touchstart.colorpicker', _jquery2.default.proxy(this.hide, this)); - (0, _jquery2.default)(this.root.document).off('mousedown.colorpicker touchstart.colorpicker', _jquery2.default.proxy(this.onClickingInside, this)); - } - }, { - key: 'isClickingInside', - value: function isClickingInside(e) { - if (!e) { - return false; - } - - return this.isOrIsInside(this.popoverTip, e.currentTarget) || this.isOrIsInside(this.popoverTip, e.target) || this.isOrIsInside(this.colorpicker.picker, e.currentTarget) || this.isOrIsInside(this.colorpicker.picker, e.target); - } - }, { - key: 'isOrIsInside', - value: function isOrIsInside(container, element) { - if (!container || !element) { - return false; - } - - element = (0, _jquery2.default)(element); - - return element.is(container) || container.find(element).length > 0; - } - }, { - key: 'onClickingInside', - value: function onClickingInside(e) { - this.clicking = this.isClickingInside(e); - } - }, { - key: 'createPopover', - value: function createPopover() { - var cp = this.colorpicker; - - this.popoverTarget = this.hasAddon ? this.addon : this.input; - - cp.picker.addClass('colorpicker-bs-popover-content'); - - this.popoverTarget.popover(_jquery2.default.extend(true, {}, _options2.default.popover, cp.options.popover, { trigger: 'manual', content: cp.picker, html: true })); - - this.popoverTip = (0, _jquery2.default)(this.popoverTarget.popover('getTipElement').data('bs.popover').tip); - this.popoverTip.addClass('colorpicker-bs-popover'); - - this.popoverTarget.on('shown.bs.popover', _jquery2.default.proxy(this.fireShow, this)); - this.popoverTarget.on('hidden.bs.popover', _jquery2.default.proxy(this.fireHide, this)); - } - - /** - * If the widget is not inside a container or inline, rearranges its position relative to its element offset. - * - * @param {Event} [e] - * @private - */ - - }, { - key: 'reposition', - value: function reposition(e) { - if (this.popoverTarget && this.isVisible()) { - this.popoverTarget.popover('update'); - } - } - - /** - * Toggles the colorpicker between visible or hidden - * - * @fires Colorpicker#colorpickerShow - * @fires Colorpicker#colorpickerHide - * @param {Event} [e] - */ - - }, { - key: 'toggle', - value: function toggle(e) { - if (this.isVisible()) { - this.hide(e); - } else { - this.show(e); - } - } - - /** - * Shows the colorpicker widget if hidden. - * - * @fires Colorpicker#colorpickerShow - * @param {Event} [e] - */ - - }, { - key: 'show', - value: function show(e) { - if (this.isVisible() || this.showing || this.hidding) { - return; - } - - this.showing = true; - this.hidding = false; - this.clicking = false; - - var cp = this.colorpicker; - - cp.lastEvent.alias = 'show'; - cp.lastEvent.e = e; - - // Prevent showing browser native HTML5 colorpicker - if (e && (!this.hasInput || this.input.attr('type') === 'color') && e && e.preventDefault) { - e.stopPropagation(); - e.preventDefault(); - } - - // If it's a popover, add event to the document to hide the picker when clicking outside of it - if (this.isPopover) { - (0, _jquery2.default)(this.root).on('resize.colorpicker', _jquery2.default.proxy(this.reposition, this)); - } - - // add visible class before popover is shown - cp.picker.addClass('colorpicker-visible').removeClass('colorpicker-hidden'); - - if (this.popoverTarget) { - this.popoverTarget.popover('show'); - } else { - this.fireShow(); - } - } - }, { - key: 'fireShow', - value: function fireShow() { - this.hidding = false; - this.showing = false; - - if (this.isPopover) { - // Add event to hide on outside click - (0, _jquery2.default)(this.root.document).on('mousedown.colorpicker touchstart.colorpicker', _jquery2.default.proxy(this.hide, this)); - (0, _jquery2.default)(this.root.document).on('mousedown.colorpicker touchstart.colorpicker', _jquery2.default.proxy(this.onClickingInside, this)); - } - - /** - * (Colorpicker) When show() is called and the widget can be shown. - * - * @event Colorpicker#colorpickerShow - */ - this.colorpicker.trigger('colorpickerShow'); - } - - /** - * Hides the colorpicker widget. - * Hide is prevented when it is triggered by an event whose target element has been clicked/touched. - * - * @fires Colorpicker#colorpickerHide - * @param {Event} [e] - */ - - }, { - key: 'hide', - value: function hide(e) { - if (this.isHidden() || this.showing || this.hidding) { - return; - } - - var cp = this.colorpicker, - clicking = this.clicking || this.isClickingInside(e); - - this.hidding = true; - this.showing = false; - this.clicking = false; - - cp.lastEvent.alias = 'hide'; - cp.lastEvent.e = e; - - // TODO: fix having to click twice outside when losing focus and last 2 clicks where inside the colorpicker - - // Prevent hide if triggered by an event and an element inside the colorpicker has been clicked/touched - if (clicking) { - this.hidding = false; - return; - } - - if (this.popoverTarget) { - this.popoverTarget.popover('hide'); - } else { - this.fireHide(); - } - } - }, { - key: 'fireHide', - value: function fireHide() { - this.hidding = false; - this.showing = false; - - var cp = this.colorpicker; - - // add hidden class after popover is hidden - cp.picker.addClass('colorpicker-hidden').removeClass('colorpicker-visible'); - - // Unbind window and document events, since there is no need to keep them while the popup is hidden - (0, _jquery2.default)(this.root).off('resize.colorpicker', _jquery2.default.proxy(this.reposition, this)); - (0, _jquery2.default)(this.root.document).off('mousedown.colorpicker touchstart.colorpicker', _jquery2.default.proxy(this.hide, this)); - (0, _jquery2.default)(this.root.document).off('mousedown.colorpicker touchstart.colorpicker', _jquery2.default.proxy(this.onClickingInside, this)); - - /** - * (Colorpicker) When hide() is called and the widget can be hidden. - * - * @event Colorpicker#colorpickerHide - */ - cp.trigger('colorpickerHide'); - } - }, { - key: 'focus', - value: function focus() { - if (this.hasAddon) { - return this.addon.focus(); - } - if (this.hasInput) { - return this.input.focus(); - } - return false; - } - - /** - * Returns true if the colorpicker element has the colorpicker-visible class and not the colorpicker-hidden one. - * False otherwise. - * - * @returns {boolean} - */ - - }, { - key: 'isVisible', - value: function isVisible() { - return this.colorpicker.picker.hasClass('colorpicker-visible') && !this.colorpicker.picker.hasClass('colorpicker-hidden'); - } - - /** - * Returns true if the colorpicker element has the colorpicker-hidden class and not the colorpicker-visible one. - * False otherwise. - * - * @returns {boolean} - */ - - }, { - key: 'isHidden', - value: function isHidden() { - return this.colorpicker.picker.hasClass('colorpicker-hidden') && !this.colorpicker.picker.hasClass('colorpicker-visible'); - } - }, { - key: 'input', - get: function get() { - return this.colorpicker.inputHandler.input; - } - - /** - * @private - * @returns {boolean} - */ - - }, { - key: 'hasInput', - get: function get() { - return this.colorpicker.inputHandler.hasInput(); - } - - /** - * @private - * @returns {jQuery|false} - */ - - }, { - key: 'addon', - get: function get() { - return this.colorpicker.addonHandler.addon; - } - - /** - * @private - * @returns {boolean} - */ - - }, { - key: 'hasAddon', - get: function get() { - return this.colorpicker.addonHandler.hasAddon(); - } - - /** - * @private - * @returns {boolean} - */ - - }, { - key: 'isPopover', - get: function get() { - return !this.colorpicker.options.inline && !!this.popoverTip; - } - }]); - - return PopupHandler; -}(); - -exports.default = PopupHandler; -module.exports = exports.default; - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _ColorItem = __webpack_require__(2); - -var _ColorItem2 = _interopRequireDefault(_ColorItem); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Handles everything related to the colorpicker input - * @ignore - */ -var InputHandler = function () { - /** - * @param {Colorpicker} colorpicker - */ - function InputHandler(colorpicker) { - _classCallCheck(this, InputHandler); - - /** - * @type {Colorpicker} - */ - this.colorpicker = colorpicker; - /** - * @type {jQuery|false} - */ - this.input = this.colorpicker.element.is('input') ? this.colorpicker.element : this.colorpicker.options.input ? this.colorpicker.element.find(this.colorpicker.options.input) : false; - - if (this.input && this.input.length === 0) { - this.input = false; - } - - this._initValue(); - } - - _createClass(InputHandler, [{ - key: 'bind', - value: function bind() { - if (!this.hasInput()) { - return; - } - this.input.on({ - 'keyup.colorpicker': _jquery2.default.proxy(this.onkeyup, this) - }); - this.input.on({ - 'change.colorpicker': _jquery2.default.proxy(this.onchange, this) - }); - } - }, { - key: 'unbind', - value: function unbind() { - if (!this.hasInput()) { - return; - } - this.input.off('.colorpicker'); - } - }, { - key: '_initValue', - value: function _initValue() { - if (!this.hasInput()) { - return; - } - - var val = ''; - - [ - // candidates: - this.input.val(), this.input.data('color'), this.input.attr('data-color')].map(function (item) { - if (item && val === '') { - val = item; - } - }); - - if (val instanceof _ColorItem2.default) { - val = this.getFormattedColor(val.string(this.colorpicker.format)); - } else if (!(typeof val === 'string' || val instanceof String)) { - val = ''; - } - - this.input.prop('value', val); - } - - /** - * Returns the color string from the input value. - * If there is no input the return value is false. - * - * @returns {String|boolean} - */ - - }, { - key: 'getValue', - value: function getValue() { - if (!this.hasInput()) { - return false; - } - - return this.input.val(); - } - - /** - * If the input element is present, it updates the value with the current color object color string. - * If the value is changed, this method fires a "change" event on the input element. - * - * @param {String} val - * - * @fires Colorpicker#change - */ - - }, { - key: 'setValue', - value: function setValue(val) { - if (!this.hasInput()) { - return; - } - - var inputVal = this.input.prop('value'); - - val = val ? val : ''; - - if (val === (inputVal ? inputVal : '')) { - // No need to set value or trigger any event if nothing changed - return; - } - - this.input.prop('value', val); - - /** - * (Input) Triggered on the input element when a new color is selected. - * - * @event Colorpicker#change - */ - this.input.trigger({ - type: 'change', - colorpicker: this.colorpicker, - color: this.colorpicker.color, - value: val - }); - } - - /** - * Returns the formatted color string, with the formatting options applied - * (e.g. useHashPrefix) - * - * @param {String|null} val - * - * @returns {String} - */ - - }, { - key: 'getFormattedColor', - value: function getFormattedColor() { - var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - - val = val ? val : this.colorpicker.colorHandler.getColorString(); - - if (!val) { - return ''; - } - - val = this.colorpicker.colorHandler.resolveColorDelegate(val, false); - - if (this.colorpicker.options.useHashPrefix === false) { - val = val.replace(/^#/g, ''); - } - - return val; - } - - /** - * Returns true if the widget has an associated input element, false otherwise - * @returns {boolean} - */ - - }, { - key: 'hasInput', - value: function hasInput() { - return this.input !== false; - } - - /** - * Returns true if the input exists and is disabled - * @returns {boolean} - */ - - }, { - key: 'isEnabled', - value: function isEnabled() { - return this.hasInput() && !this.isDisabled(); - } - - /** - * Returns true if the input exists and is disabled - * @returns {boolean} - */ - - }, { - key: 'isDisabled', - value: function isDisabled() { - return this.hasInput() && this.input.prop('disabled') === true; - } - - /** - * Disables the input if any - * - * @fires Colorpicker#colorpickerDisable - * @returns {boolean} - */ - - }, { - key: 'disable', - value: function disable() { - if (this.hasInput()) { - this.input.prop('disabled', true); - } - } - - /** - * Enables the input if any - * - * @fires Colorpicker#colorpickerEnable - * @returns {boolean} - */ - - }, { - key: 'enable', - value: function enable() { - if (this.hasInput()) { - this.input.prop('disabled', false); - } - } - - /** - * Calls setValue with the current internal color value - * - * @fires Colorpicker#change - */ - - }, { - key: 'update', - value: function update() { - if (!this.hasInput()) { - return; - } - - if (this.colorpicker.options.autoInputFallback === false && this.colorpicker.colorHandler.isInvalidColor()) { - // prevent update if color is invalid, autoInputFallback is disabled and the last event is keyup. - return; - } - - this.setValue(this.getFormattedColor()); - } - - /** - * Function triggered when the input has changed, so the colorpicker gets updated. - * - * @private - * @param {Event} e - * @returns {boolean} - */ - - }, { - key: 'onchange', - value: function onchange(e) { - this.colorpicker.lastEvent.alias = 'input.change'; - this.colorpicker.lastEvent.e = e; - - var val = this.getValue(); - - if (val !== e.value) { - this.colorpicker.setValue(val); - } - } - - /** - * Function triggered after a keyboard key has been released. - * - * @private - * @param {Event} e - * @returns {boolean} - */ - - }, { - key: 'onkeyup', - value: function onkeyup(e) { - this.colorpicker.lastEvent.alias = 'input.keyup'; - this.colorpicker.lastEvent.e = e; - - var val = this.getValue(); - - if (val !== e.value) { - this.colorpicker.setValue(val); - } - } - }]); - - return InputHandler; -}(); - -exports.default = InputHandler; -module.exports = exports.default; - -/***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var colorString = __webpack_require__(17); -var convert = __webpack_require__(20); - -var _slice = [].slice; - -var skippedModels = [ - // to be honest, I don't really feel like keyword belongs in color convert, but eh. - 'keyword', - - // gray conflicts with some method names, and has its own method defined. - 'gray', - - // shouldn't really be in color-convert either... - 'hex' -]; - -var hashedModelKeys = {}; -Object.keys(convert).forEach(function (model) { - hashedModelKeys[_slice.call(convert[model].labels).sort().join('')] = model; -}); - -var limiters = {}; - -function Color(obj, model) { - if (!(this instanceof Color)) { - return new Color(obj, model); - } - - if (model && model in skippedModels) { - model = null; - } - - if (model && !(model in convert)) { - throw new Error('Unknown model: ' + model); - } - - var i; - var channels; - - if (obj == null) { // eslint-disable-line no-eq-null,eqeqeq - this.model = 'rgb'; - this.color = [0, 0, 0]; - this.valpha = 1; - } else if (obj instanceof Color) { - this.model = obj.model; - this.color = obj.color.slice(); - this.valpha = obj.valpha; - } else if (typeof obj === 'string') { - var result = colorString.get(obj); - if (result === null) { - throw new Error('Unable to parse color from string: ' + obj); - } - - this.model = result.model; - channels = convert[this.model].channels; - this.color = result.value.slice(0, channels); - this.valpha = typeof result.value[channels] === 'number' ? result.value[channels] : 1; - } else if (obj.length) { - this.model = model || 'rgb'; - channels = convert[this.model].channels; - var newArr = _slice.call(obj, 0, channels); - this.color = zeroArray(newArr, channels); - this.valpha = typeof obj[channels] === 'number' ? obj[channels] : 1; - } else if (typeof obj === 'number') { - // this is always RGB - can be converted later on. - obj &= 0xFFFFFF; - this.model = 'rgb'; - this.color = [ - (obj >> 16) & 0xFF, - (obj >> 8) & 0xFF, - obj & 0xFF - ]; - this.valpha = 1; - } else { - this.valpha = 1; - - var keys = Object.keys(obj); - if ('alpha' in obj) { - keys.splice(keys.indexOf('alpha'), 1); - this.valpha = typeof obj.alpha === 'number' ? obj.alpha : 0; - } - - var hashedKeys = keys.sort().join(''); - if (!(hashedKeys in hashedModelKeys)) { - throw new Error('Unable to parse color from object: ' + JSON.stringify(obj)); - } - - this.model = hashedModelKeys[hashedKeys]; - - var labels = convert[this.model].labels; - var color = []; - for (i = 0; i < labels.length; i++) { - color.push(obj[labels[i]]); - } - - this.color = zeroArray(color); - } - - // perform limitations (clamping, etc.) - if (limiters[this.model]) { - channels = convert[this.model].channels; - for (i = 0; i < channels; i++) { - var limit = limiters[this.model][i]; - if (limit) { - this.color[i] = limit(this.color[i]); - } - } - } - - this.valpha = Math.max(0, Math.min(1, this.valpha)); - - if (Object.freeze) { - Object.freeze(this); - } -} - -Color.prototype = { - toString: function () { - return this.string(); - }, - - toJSON: function () { - return this[this.model](); - }, - - string: function (places) { - var self = this.model in colorString.to ? this : this.rgb(); - self = self.round(typeof places === 'number' ? places : 1); - var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); - return colorString.to[self.model](args); - }, - - percentString: function (places) { - var self = this.rgb().round(typeof places === 'number' ? places : 1); - var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); - return colorString.to.rgb.percent(args); - }, - - array: function () { - return this.valpha === 1 ? this.color.slice() : this.color.concat(this.valpha); - }, - - object: function () { - var result = {}; - var channels = convert[this.model].channels; - var labels = convert[this.model].labels; - - for (var i = 0; i < channels; i++) { - result[labels[i]] = this.color[i]; - } - - if (this.valpha !== 1) { - result.alpha = this.valpha; - } - - return result; - }, - - unitArray: function () { - var rgb = this.rgb().color; - rgb[0] /= 255; - rgb[1] /= 255; - rgb[2] /= 255; - - if (this.valpha !== 1) { - rgb.push(this.valpha); - } - - return rgb; - }, - - unitObject: function () { - var rgb = this.rgb().object(); - rgb.r /= 255; - rgb.g /= 255; - rgb.b /= 255; - - if (this.valpha !== 1) { - rgb.alpha = this.valpha; - } - - return rgb; - }, - - round: function (places) { - places = Math.max(places || 0, 0); - return new Color(this.color.map(roundToPlace(places)).concat(this.valpha), this.model); - }, - - alpha: function (val) { - if (arguments.length) { - return new Color(this.color.concat(Math.max(0, Math.min(1, val))), this.model); - } - - return this.valpha; - }, - - // rgb - red: getset('rgb', 0, maxfn(255)), - green: getset('rgb', 1, maxfn(255)), - blue: getset('rgb', 2, maxfn(255)), - - hue: getset(['hsl', 'hsv', 'hsl', 'hwb', 'hcg'], 0, function (val) { return ((val % 360) + 360) % 360; }), // eslint-disable-line brace-style - - saturationl: getset('hsl', 1, maxfn(100)), - lightness: getset('hsl', 2, maxfn(100)), - - saturationv: getset('hsv', 1, maxfn(100)), - value: getset('hsv', 2, maxfn(100)), - - chroma: getset('hcg', 1, maxfn(100)), - gray: getset('hcg', 2, maxfn(100)), - - white: getset('hwb', 1, maxfn(100)), - wblack: getset('hwb', 2, maxfn(100)), - - cyan: getset('cmyk', 0, maxfn(100)), - magenta: getset('cmyk', 1, maxfn(100)), - yellow: getset('cmyk', 2, maxfn(100)), - black: getset('cmyk', 3, maxfn(100)), - - x: getset('xyz', 0, maxfn(100)), - y: getset('xyz', 1, maxfn(100)), - z: getset('xyz', 2, maxfn(100)), - - l: getset('lab', 0, maxfn(100)), - a: getset('lab', 1), - b: getset('lab', 2), - - keyword: function (val) { - if (arguments.length) { - return new Color(val); - } - - return convert[this.model].keyword(this.color); - }, - - hex: function (val) { - if (arguments.length) { - return new Color(val); - } - - return colorString.to.hex(this.rgb().round().color); - }, - - rgbNumber: function () { - var rgb = this.rgb().color; - return ((rgb[0] & 0xFF) << 16) | ((rgb[1] & 0xFF) << 8) | (rgb[2] & 0xFF); - }, - - luminosity: function () { - // http://www.w3.org/TR/WCAG20/#relativeluminancedef - var rgb = this.rgb().color; - - var lum = []; - for (var i = 0; i < rgb.length; i++) { - var chan = rgb[i] / 255; - lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); - } - - return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; - }, - - contrast: function (color2) { - // http://www.w3.org/TR/WCAG20/#contrast-ratiodef - var lum1 = this.luminosity(); - var lum2 = color2.luminosity(); - - if (lum1 > lum2) { - return (lum1 + 0.05) / (lum2 + 0.05); - } - - return (lum2 + 0.05) / (lum1 + 0.05); - }, - - level: function (color2) { - var contrastRatio = this.contrast(color2); - if (contrastRatio >= 7.1) { - return 'AAA'; - } - - return (contrastRatio >= 4.5) ? 'AA' : ''; - }, - - isDark: function () { - // YIQ equation from http://24ways.org/2010/calculating-color-contrast - var rgb = this.rgb().color; - var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; - return yiq < 128; - }, - - isLight: function () { - return !this.isDark(); - }, - - negate: function () { - var rgb = this.rgb(); - for (var i = 0; i < 3; i++) { - rgb.color[i] = 255 - rgb.color[i]; - } - return rgb; - }, - - lighten: function (ratio) { - var hsl = this.hsl(); - hsl.color[2] += hsl.color[2] * ratio; - return hsl; - }, - - darken: function (ratio) { - var hsl = this.hsl(); - hsl.color[2] -= hsl.color[2] * ratio; - return hsl; - }, - - saturate: function (ratio) { - var hsl = this.hsl(); - hsl.color[1] += hsl.color[1] * ratio; - return hsl; - }, - - desaturate: function (ratio) { - var hsl = this.hsl(); - hsl.color[1] -= hsl.color[1] * ratio; - return hsl; - }, - - whiten: function (ratio) { - var hwb = this.hwb(); - hwb.color[1] += hwb.color[1] * ratio; - return hwb; - }, - - blacken: function (ratio) { - var hwb = this.hwb(); - hwb.color[2] += hwb.color[2] * ratio; - return hwb; - }, - - grayscale: function () { - // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale - var rgb = this.rgb().color; - var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; - return Color.rgb(val, val, val); - }, - - fade: function (ratio) { - return this.alpha(this.valpha - (this.valpha * ratio)); - }, - - opaquer: function (ratio) { - return this.alpha(this.valpha + (this.valpha * ratio)); - }, - - rotate: function (degrees) { - var hsl = this.hsl(); - var hue = hsl.color[0]; - hue = (hue + degrees) % 360; - hue = hue < 0 ? 360 + hue : hue; - hsl.color[0] = hue; - return hsl; - }, - - mix: function (mixinColor, weight) { - // ported from sass implementation in C - // https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 - if (!mixinColor || !mixinColor.rgb) { - throw new Error('Argument to "mix" was not a Color instance, but rather an instance of ' + typeof mixinColor); - } - var color1 = mixinColor.rgb(); - var color2 = this.rgb(); - var p = weight === undefined ? 0.5 : weight; - - var w = 2 * p - 1; - var a = color1.alpha() - color2.alpha(); - - var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - return Color.rgb( - w1 * color1.red() + w2 * color2.red(), - w1 * color1.green() + w2 * color2.green(), - w1 * color1.blue() + w2 * color2.blue(), - color1.alpha() * p + color2.alpha() * (1 - p)); - } -}; - -// model conversion methods and static constructors -Object.keys(convert).forEach(function (model) { - if (skippedModels.indexOf(model) !== -1) { - return; - } - - var channels = convert[model].channels; - - // conversion methods - Color.prototype[model] = function () { - if (this.model === model) { - return new Color(this); - } - - if (arguments.length) { - return new Color(arguments, model); - } - - var newAlpha = typeof arguments[channels] === 'number' ? channels : this.valpha; - return new Color(assertArray(convert[this.model][model].raw(this.color)).concat(newAlpha), model); - }; - - // 'static' construction methods - Color[model] = function (color) { - if (typeof color === 'number') { - color = zeroArray(_slice.call(arguments), channels); - } - return new Color(color, model); - }; -}); - -function roundTo(num, places) { - return Number(num.toFixed(places)); -} - -function roundToPlace(places) { - return function (num) { - return roundTo(num, places); - }; -} - -function getset(model, channel, modifier) { - model = Array.isArray(model) ? model : [model]; - - model.forEach(function (m) { - (limiters[m] || (limiters[m] = []))[channel] = modifier; - }); - - model = model[0]; - - return function (val) { - var result; - - if (arguments.length) { - if (modifier) { - val = modifier(val); - } - - result = this[model](); - result.color[channel] = val; - return result; - } - - result = this[model]().color[channel]; - if (modifier) { - result = modifier(result); - } - - return result; - }; -} - -function maxfn(max) { - return function (v) { - return Math.max(0, Math.min(max, v)); - }; -} - -function assertArray(val) { - return Array.isArray(val) ? val : [val]; -} - -function zeroArray(arr, length) { - for (var i = 0; i < length; i++) { - if (typeof arr[i] !== 'number') { - arr[i] = 0; - } - } - - return arr; -} - -module.exports = Color; - - -/***/ }), -/* 17 */ -/***/ (function(module, exports, __webpack_require__) { - -/* MIT license */ -var colorNames = __webpack_require__(5); -var swizzle = __webpack_require__(18); - -var reverseNames = {}; - -// create a list of reverse color names -for (var name in colorNames) { - if (colorNames.hasOwnProperty(name)) { - reverseNames[colorNames[name]] = name; - } -} - -var cs = module.exports = { - to: {}, - get: {} -}; - -cs.get = function (string) { - var prefix = string.substring(0, 3).toLowerCase(); - var val; - var model; - switch (prefix) { - case 'hsl': - val = cs.get.hsl(string); - model = 'hsl'; - break; - case 'hwb': - val = cs.get.hwb(string); - model = 'hwb'; - break; - default: - val = cs.get.rgb(string); - model = 'rgb'; - break; - } - - if (!val) { - return null; - } - - return {model: model, value: val}; -}; - -cs.get.rgb = function (string) { - if (!string) { - return null; - } - - var abbr = /^#([a-f0-9]{3,4})$/i; - var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i; - var rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; - var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; - var keyword = /(\D+)/; - - var rgb = [0, 0, 0, 1]; - var match; - var i; - var hexAlpha; - - if (match = string.match(hex)) { - hexAlpha = match[2]; - match = match[1]; - - for (i = 0; i < 3; i++) { - // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 - var i2 = i * 2; - rgb[i] = parseInt(match.slice(i2, i2 + 2), 16); - } - - if (hexAlpha) { - rgb[3] = Math.round((parseInt(hexAlpha, 16) / 255) * 100) / 100; - } - } else if (match = string.match(abbr)) { - match = match[1]; - hexAlpha = match[3]; - - for (i = 0; i < 3; i++) { - rgb[i] = parseInt(match[i] + match[i], 16); - } - - if (hexAlpha) { - rgb[3] = Math.round((parseInt(hexAlpha + hexAlpha, 16) / 255) * 100) / 100; - } - } else if (match = string.match(rgba)) { - for (i = 0; i < 3; i++) { - rgb[i] = parseInt(match[i + 1], 0); - } - - if (match[4]) { - rgb[3] = parseFloat(match[4]); - } - } else if (match = string.match(per)) { - for (i = 0; i < 3; i++) { - rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); - } - - if (match[4]) { - rgb[3] = parseFloat(match[4]); - } - } else if (match = string.match(keyword)) { - if (match[1] === 'transparent') { - return [0, 0, 0, 0]; - } - - rgb = colorNames[match[1]]; - - if (!rgb) { - return null; - } - - rgb[3] = 1; - - return rgb; - } else { - return null; - } - - for (i = 0; i < 3; i++) { - rgb[i] = clamp(rgb[i], 0, 255); - } - rgb[3] = clamp(rgb[3], 0, 1); - - return rgb; -}; - -cs.get.hsl = function (string) { - if (!string) { - return null; - } - - var hsl = /^hsla?\(\s*([+-]?(?:\d*\.)?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; - var match = string.match(hsl); - - if (match) { - var alpha = parseFloat(match[4]); - var h = (parseFloat(match[1]) + 360) % 360; - var s = clamp(parseFloat(match[2]), 0, 100); - var l = clamp(parseFloat(match[3]), 0, 100); - var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); - - return [h, s, l, a]; - } - - return null; -}; - -cs.get.hwb = function (string) { - if (!string) { - return null; - } - - var hwb = /^hwb\(\s*([+-]?\d*[\.]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; - var match = string.match(hwb); - - if (match) { - var alpha = parseFloat(match[4]); - var h = ((parseFloat(match[1]) % 360) + 360) % 360; - var w = clamp(parseFloat(match[2]), 0, 100); - var b = clamp(parseFloat(match[3]), 0, 100); - var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); - return [h, w, b, a]; - } - - return null; -}; - -cs.to.hex = function () { - var rgba = swizzle(arguments); - - return ( - '#' + - hexDouble(rgba[0]) + - hexDouble(rgba[1]) + - hexDouble(rgba[2]) + - (rgba[3] < 1 - ? (hexDouble(Math.round(rgba[3] * 255))) - : '') - ); -}; - -cs.to.rgb = function () { - var rgba = swizzle(arguments); - - return rgba.length < 4 || rgba[3] === 1 - ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' - : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; -}; - -cs.to.rgb.percent = function () { - var rgba = swizzle(arguments); - - var r = Math.round(rgba[0] / 255 * 100); - var g = Math.round(rgba[1] / 255 * 100); - var b = Math.round(rgba[2] / 255 * 100); - - return rgba.length < 4 || rgba[3] === 1 - ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' - : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; -}; - -cs.to.hsl = function () { - var hsla = swizzle(arguments); - return hsla.length < 4 || hsla[3] === 1 - ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' - : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; -}; - -// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax -// (hwb have alpha optional & 1 is default value) -cs.to.hwb = function () { - var hwba = swizzle(arguments); - - var a = ''; - if (hwba.length >= 4 && hwba[3] !== 1) { - a = ', ' + hwba[3]; - } - - return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; -}; - -cs.to.keyword = function (rgb) { - return reverseNames[rgb.slice(0, 3)]; -}; - -// helpers -function clamp(num, min, max) { - return Math.min(Math.max(min, num), max); -} - -function hexDouble(num) { - var str = num.toString(16).toUpperCase(); - return (str.length < 2) ? '0' + str : str; -} - - -/***/ }), -/* 18 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isArrayish = __webpack_require__(19); - -var concat = Array.prototype.concat; -var slice = Array.prototype.slice; - -var swizzle = module.exports = function swizzle(args) { - var results = []; - - for (var i = 0, len = args.length; i < len; i++) { - var arg = args[i]; - - if (isArrayish(arg)) { - // http://jsperf.com/javascript-array-concat-vs-push/98 - results = concat.call(results, slice.call(arg)); - } else { - results.push(arg); - } - } - - return results; -}; - -swizzle.wrap = function (fn) { - return function () { - return fn(swizzle(arguments)); - }; -}; - - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = function isArrayish(obj) { - if (!obj) { - return false; - } - - return obj instanceof Array || Array.isArray(obj) || - (obj.length >= 0 && obj.splice instanceof Function); -}; - - -/***/ }), -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { - -var conversions = __webpack_require__(6); -var route = __webpack_require__(21); - -var convert = {}; - -var models = Object.keys(conversions); - -function wrapRaw(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; - } - - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); - } - - return fn(args); - }; - - // preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } - - return wrappedFn; -} - -function wrapRounded(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; - } - - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); - } - - var result = fn(args); - - // we're assuming the result is an array here. - // see notice in conversions.js; don't use box types - // in conversion functions. - if (typeof result === 'object') { - for (var len = result.length, i = 0; i < len; i++) { - result[i] = Math.round(result[i]); - } - } - - return result; - }; - - // preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } - - return wrappedFn; -} - -models.forEach(function (fromModel) { - convert[fromModel] = {}; - - Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); - Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); - - var routes = route(fromModel); - var routeModels = Object.keys(routes); - - routeModels.forEach(function (toModel) { - var fn = routes[toModel]; - - convert[fromModel][toModel] = wrapRounded(fn); - convert[fromModel][toModel].raw = wrapRaw(fn); - }); -}); - -module.exports = convert; - - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - -var conversions = __webpack_require__(6); - -/* - this function routes a model to all other models. - - all functions that are routed have a property `.conversion` attached - to the returned synthetic function. This property is an array - of strings, each with the steps in between the 'from' and 'to' - color models (inclusive). - - conversions that are not possible simply are not included. -*/ - -function buildGraph() { - var graph = {}; - // https://jsperf.com/object-keys-vs-for-in-with-closure/3 - var models = Object.keys(conversions); - - for (var len = models.length, i = 0; i < len; i++) { - graph[models[i]] = { - // http://jsperf.com/1-vs-infinity - // micro-opt, but this is simple. - distance: -1, - parent: null - }; - } - - return graph; -} - -// https://en.wikipedia.org/wiki/Breadth-first_search -function deriveBFS(fromModel) { - var graph = buildGraph(); - var queue = [fromModel]; // unshift -> queue -> pop - - graph[fromModel].distance = 0; - - while (queue.length) { - var current = queue.pop(); - var adjacents = Object.keys(conversions[current]); - - for (var len = adjacents.length, i = 0; i < len; i++) { - var adjacent = adjacents[i]; - var node = graph[adjacent]; - - if (node.distance === -1) { - node.distance = graph[current].distance + 1; - node.parent = current; - queue.unshift(adjacent); - } - } - } - - return graph; -} - -function link(from, to) { - return function (args) { - return to(from(args)); - }; -} - -function wrapConversion(toModel, graph) { - var path = [graph[toModel].parent, toModel]; - var fn = conversions[graph[toModel].parent][toModel]; - - var cur = graph[toModel].parent; - while (graph[cur].parent) { - path.unshift(graph[cur].parent); - fn = link(conversions[graph[cur].parent][cur], fn); - cur = graph[cur].parent; - } - - fn.conversion = path; - return fn; -} - -module.exports = function (fromModel) { - var graph = deriveBFS(fromModel); - var conversion = {}; - - var models = Object.keys(graph); - for (var len = models.length, i = 0; i < len; i++) { - var toModel = models[i]; - var node = graph[toModel]; - - if (node.parent === null) { - // no possible conversion, or this node is the source model. - continue; - } - - conversion[toModel] = wrapConversion(toModel, graph); - } - - return conversion; -}; - - - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _ColorItem = __webpack_require__(2); - -var _ColorItem2 = _interopRequireDefault(_ColorItem); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Handles everything related to the colorpicker color - * @ignore - */ -var ColorHandler = function () { - /** - * @param {Colorpicker} colorpicker - */ - function ColorHandler(colorpicker) { - _classCallCheck(this, ColorHandler); - - /** - * @type {Colorpicker} - */ - this.colorpicker = colorpicker; - } - - /** - * @returns {*|String|ColorItem} - */ - - - _createClass(ColorHandler, [{ - key: 'bind', - value: function bind() { - // if the color option is set - if (this.colorpicker.options.color) { - this.color = this.createColor(this.colorpicker.options.color); - return; - } - - // if element[color] is empty and the input has a value - if (!this.color && !!this.colorpicker.inputHandler.getValue()) { - this.color = this.createColor(this.colorpicker.inputHandler.getValue(), this.colorpicker.options.autoInputFallback); - } - } - }, { - key: 'unbind', - value: function unbind() { - this.colorpicker.element.removeData('color'); - } - - /** - * Returns the color string from the input value or the 'data-color' attribute of the input or element. - * If empty, it returns the defaultValue parameter. - * - * @returns {String|*} - */ - - }, { - key: 'getColorString', - value: function getColorString() { - if (!this.hasColor()) { - return ''; - } - - return this.color.string(this.format); - } - - /** - * Sets the color value - * - * @param {String|ColorItem} val - */ - - }, { - key: 'setColorString', - value: function setColorString(val) { - var color = val ? this.createColor(val) : null; - - this.color = color ? color : null; - } - - /** - * Creates a new color using the widget instance options (fallbackColor, format). - * - * @fires Colorpicker#colorpickerInvalid - * @param {*} val - * @param {boolean} fallbackOnInvalid - * @returns {ColorItem} - */ - - }, { - key: 'createColor', - value: function createColor(val) { - var fallbackOnInvalid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - var color = new _ColorItem2.default(this.resolveColorDelegate(val), this.format); - - if (!color.isValid()) { - if (fallbackOnInvalid) { - color = this.getFallbackColor(); - } - - /** - * (Colorpicker) Fired when the color is invalid and the fallback color is going to be used. - * - * @event Colorpicker#colorpickerInvalid - */ - this.colorpicker.trigger('colorpickerInvalid', color, val); - } - - if (!this.isAlphaEnabled()) { - // Alpha is disabled - color.alpha = 1; - } - - return color; - } - }, { - key: 'getFallbackColor', - value: function getFallbackColor() { - if (this.fallback && this.fallback === this.color) { - return this.color; - } - - var fallback = this.resolveColorDelegate(this.fallback); - - var color = new _ColorItem2.default(fallback, this.format); - - if (!color.isValid()) { - console.warn('The fallback color is invalid. Falling back to the previous color or black if any.'); - return this.color ? this.color : new _ColorItem2.default('#000000', this.format); - } - - return color; - } - - /** - * @returns {ColorItem} - */ - - }, { - key: 'assureColor', - value: function assureColor() { - if (!this.hasColor()) { - this.color = this.getFallbackColor(); - } - - return this.color; - } - - /** - * Delegates the color resolution to the colorpicker extensions. - * - * @param {String|*} color - * @param {boolean} realColor if true, the color should resolve into a real (not named) color code - * @returns {ColorItem|String|*|null} - */ - - }, { - key: 'resolveColorDelegate', - value: function resolveColorDelegate(color) { - var realColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - var extResolvedColor = false; - - _jquery2.default.each(this.colorpicker.extensions, function (name, ext) { - if (extResolvedColor !== false) { - // skip if resolved - return; - } - extResolvedColor = ext.resolveColor(color, realColor); - }); - - return extResolvedColor ? extResolvedColor : color; - } - - /** - * Checks if there is a color object, that it is valid and it is not a fallback - * @returns {boolean} - */ - - }, { - key: 'isInvalidColor', - value: function isInvalidColor() { - return !this.hasColor() || !this.color.isValid(); - } - - /** - * Returns true if the useAlpha option is exactly true, false otherwise - * @returns {boolean} - */ - - }, { - key: 'isAlphaEnabled', - value: function isAlphaEnabled() { - return this.colorpicker.options.useAlpha !== false; - } - - /** - * Returns true if the current color object is an instance of Color, false otherwise. - * @returns {boolean} - */ - - }, { - key: 'hasColor', - value: function hasColor() { - return this.color instanceof _ColorItem2.default; - } - }, { - key: 'fallback', - get: function get() { - return this.colorpicker.options.fallbackColor ? this.colorpicker.options.fallbackColor : this.hasColor() ? this.color : null; - } - - /** - * @returns {String|null} - */ - - }, { - key: 'format', - get: function get() { - if (this.colorpicker.options.format) { - return this.colorpicker.options.format; - } - - if (this.hasColor() && this.color.hasTransparency() && this.color.format.match(/^hex/)) { - return this.isAlphaEnabled() ? 'rgba' : 'hex'; - } - - if (this.hasColor()) { - return this.color.format; - } - - return 'rgb'; - } - - /** - * Internal color getter - * - * @type {ColorItem|null} - */ - - }, { - key: 'color', - get: function get() { - return this.colorpicker.element.data('color'); - } - - /** - * Internal color setter - * - * @ignore - * @param {ColorItem|null} value - */ - , - set: function set(value) { - this.colorpicker.element.data('color', value); - - if (value instanceof _ColorItem2.default && this.colorpicker.options.format === 'auto') { - // If format is 'auto', use the first parsed one from now on - this.colorpicker.options.format = this.color.format; - } - } - }]); - - return ColorHandler; -}(); - -exports.default = ColorHandler; -module.exports = exports.default; - -/***/ }), -/* 23 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Handles everything related to the colorpicker UI - * @ignore - */ -var PickerHandler = function () { - /** - * @param {Colorpicker} colorpicker - */ - function PickerHandler(colorpicker) { - _classCallCheck(this, PickerHandler); - - /** - * @type {Colorpicker} - */ - this.colorpicker = colorpicker; - /** - * @type {jQuery} - */ - this.picker = null; - } - - _createClass(PickerHandler, [{ - key: 'bind', - value: function bind() { - /** - * @type {jQuery|HTMLElement} - */ - var picker = this.picker = (0, _jquery2.default)(this.options.template); - - if (this.options.customClass) { - picker.addClass(this.options.customClass); - } - - if (this.options.horizontal) { - picker.addClass('colorpicker-horizontal'); - } - - if (this._supportsAlphaBar()) { - this.options.useAlpha = true; - picker.addClass('colorpicker-with-alpha'); - } else { - this.options.useAlpha = false; - } - } - }, { - key: 'attach', - value: function attach() { - // Inject the colorpicker element into the DOM - var pickerParent = this.colorpicker.container ? this.colorpicker.container : null; - - if (pickerParent) { - this.picker.appendTo(pickerParent); - } - } - }, { - key: 'unbind', - value: function unbind() { - this.picker.remove(); - } - }, { - key: '_supportsAlphaBar', - value: function _supportsAlphaBar() { - return (this.options.useAlpha || this.colorpicker.colorHandler.hasColor() && this.color.hasTransparency()) && this.options.useAlpha !== false && (!this.options.format || this.options.format && !this.options.format.match(/^hex([36])?$/i)); - } - - /** - * Changes the color adjustment bars using the current color object information. - */ - - }, { - key: 'update', - value: function update() { - if (!this.colorpicker.colorHandler.hasColor()) { - return; - } - - var vertical = this.options.horizontal !== true, - slider = vertical ? this.options.sliders : this.options.slidersHorz; - - var saturationGuide = this.picker.find('.colorpicker-saturation .colorpicker-guide'), - hueGuide = this.picker.find('.colorpicker-hue .colorpicker-guide'), - alphaGuide = this.picker.find('.colorpicker-alpha .colorpicker-guide'); - - var hsva = this.color.toHsvaRatio(); - - // Set guides position - if (hueGuide.length) { - hueGuide.css(vertical ? 'top' : 'left', (vertical ? slider.hue.maxTop : slider.hue.maxLeft) * (1 - hsva.h)); - } - if (alphaGuide.length) { - alphaGuide.css(vertical ? 'top' : 'left', (vertical ? slider.alpha.maxTop : slider.alpha.maxLeft) * (1 - hsva.a)); - } - if (saturationGuide.length) { - saturationGuide.css({ - 'top': slider.saturation.maxTop - hsva.v * slider.saturation.maxTop, - 'left': hsva.s * slider.saturation.maxLeft - }); - } - - // Set saturation hue background - this.picker.find('.colorpicker-saturation').css('backgroundColor', this.color.getCloneHueOnly().toHexString()); // we only need hue - - // Set alpha color gradient - var hexColor = this.color.toHexString(); - - var alphaBg = ''; - - if (this.options.horizontal) { - alphaBg = 'linear-gradient(to right, ' + hexColor + ' 0%, transparent 100%)'; - } else { - alphaBg = 'linear-gradient(to bottom, ' + hexColor + ' 0%, transparent 100%)'; - } - - this.picker.find('.colorpicker-alpha-color').css('background', alphaBg); - } - }, { - key: 'options', - get: function get() { - return this.colorpicker.options; - } - }, { - key: 'color', - get: function get() { - return this.colorpicker.colorHandler.color; - } - }]); - - return PickerHandler; -}(); - -exports.default = PickerHandler; -module.exports = exports.default; - -/***/ }), -/* 24 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Handles everything related to the colorpicker addon - * @ignore - */ - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var AddonHandler = function () { - /** - * @param {Colorpicker} colorpicker - */ - function AddonHandler(colorpicker) { - _classCallCheck(this, AddonHandler); - - /** - * @type {Colorpicker} - */ - this.colorpicker = colorpicker; - /** - * @type {jQuery} - */ - this.addon = null; - } - - _createClass(AddonHandler, [{ - key: 'hasAddon', - value: function hasAddon() { - return !!this.addon; - } - }, { - key: 'bind', - value: function bind() { - /** - * @type {*|jQuery} - */ - this.addon = this.colorpicker.options.addon ? this.colorpicker.element.find(this.colorpicker.options.addon) : null; - - if (this.addon && this.addon.length === 0) { - // not found - this.addon = null; - } - } - }, { - key: 'unbind', - value: function unbind() { - if (this.hasAddon()) { - this.addon.off('.colorpicker'); - } - } - - /** - * If the addon element is present, its background color is updated - */ - - }, { - key: 'update', - value: function update() { - if (!this.colorpicker.colorHandler.hasColor() || !this.hasAddon()) { - return; - } - - var colorStr = this.colorpicker.colorHandler.getColorString(); - - var styles = { 'background': colorStr }; - - var icn = this.addon.find('i').eq(0); - - if (icn.length > 0) { - icn.css(styles); - } else { - this.addon.css(styles); - } - } - }]); - - return AddonHandler; -}(); - -exports.default = AddonHandler; -module.exports = exports.default; - -/***/ }) -/******/ ]); -}); -//# sourceMappingURL=bootstrap-colorpicker.js.map \ No newline at end of file diff --git a/hal-core/resources/web/js/lib/bootstrap-colorpicker.min.js b/hal-core/resources/web/js/lib/bootstrap-colorpicker.min.js deleted file mode 100644 index bfdbed0c..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-colorpicker.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/*! - * Bootstrap Colorpicker - Bootstrap Colorpicker is a modular color picker plugin for Bootstrap 4. - * @package bootstrap-colorpicker - * @version v3.2.0 - * @license MIT - * @link https://itsjavi.com/bootstrap-colorpicker/ - * @link https://github.com/itsjavi/bootstrap-colorpicker.git - */ -(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory(require("jquery"));else if(typeof define==="function"&&define.amd)define("bootstrap-colorpicker",["jquery"],factory);else if(typeof exports==="object")exports["bootstrap-colorpicker"]=factory(require("jquery"));else root["bootstrap-colorpicker"]=factory(root["jQuery"])})(window,function(__WEBPACK_EXTERNAL_MODULE__0__){return function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId]){return installedModules[moduleId].exports}var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{enumerable:true,get:getter})}};__webpack_require__.r=function(exports){if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(exports,"__esModule",{value:true})};__webpack_require__.t=function(value,mode){if(mode&1)value=__webpack_require__(value);if(mode&8)return value;if(mode&4&&typeof value==="object"&&value&&value.__esModule)return value;var ns=Object.create(null);__webpack_require__.r(ns);Object.defineProperty(ns,"default",{enumerable:true,value});if(mode&2&&typeof value!="string")for(var key in value)__webpack_require__.d(ns,key,function(key){return value[key]}.bind(null,key));return ns};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module["default"]}:function getModuleExports(){return module};__webpack_require__.d(getter,"a",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p="";return __webpack_require__(__webpack_require__.s=7)}([function(module,exports){module.exports=__WEBPACK_EXTERNAL_MODULE__0__},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};_classCallCheck(this,Extension);this.colorpicker=colorpicker;this.options=options;if(!(this.colorpicker.element&&this.colorpicker.element.length)){throw new Error("Extension: this.colorpicker.element is not valid")}this.colorpicker.element.on("colorpickerCreate.colorpicker-ext",_jquery2.default.proxy(this.onCreate,this));this.colorpicker.element.on("colorpickerDestroy.colorpicker-ext",_jquery2.default.proxy(this.onDestroy,this));this.colorpicker.element.on("colorpickerUpdate.colorpicker-ext",_jquery2.default.proxy(this.onUpdate,this));this.colorpicker.element.on("colorpickerChange.colorpicker-ext",_jquery2.default.proxy(this.onChange,this));this.colorpicker.element.on("colorpickerInvalid.colorpicker-ext",_jquery2.default.proxy(this.onInvalid,this));this.colorpicker.element.on("colorpickerShow.colorpicker-ext",_jquery2.default.proxy(this.onShow,this));this.colorpicker.element.on("colorpickerHide.colorpicker-ext",_jquery2.default.proxy(this.onHide,this));this.colorpicker.element.on("colorpickerEnable.colorpicker-ext",_jquery2.default.proxy(this.onEnable,this));this.colorpicker.element.on("colorpickerDisable.colorpicker-ext",_jquery2.default.proxy(this.onDisable,this))}_createClass(Extension,[{key:"resolveColor",value:function resolveColor(color){var realColor=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;return false}},{key:"onCreate",value:function onCreate(event){}},{key:"onDestroy",value:function onDestroy(event){this.colorpicker.element.off(".colorpicker-ext")}},{key:"onUpdate",value:function onUpdate(event){}},{key:"onChange",value:function onChange(event){}},{key:"onInvalid",value:function onInvalid(event){}},{key:"onHide",value:function onHide(event){}},{key:"onShow",value:function onShow(event){}},{key:"onDisable",value:function onDisable(event){}},{key:"onEnable",value:function onEnable(event){}}]);return Extension}();exports.default=Extension;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ColorItem=exports.HSVAColor=undefined;var _createClass=function(){function defineProperties(target,props){for(var i=0;i1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key]}if(arguments.length===0){return this._color}var result=this._color[fn].apply(this._color,args);if(!(result instanceof _color2.default)){return result}return new ColorItem(result,this.format)}},{key:"original",get:function get(){return this._original}}],[{key:"HSVAColor",get:function get(){return HSVAColor}}]);function ColorItem(){var color=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;var format=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;_classCallCheck(this,ColorItem);this.replace(color,format)}_createClass(ColorItem,[{key:"replace",value:function replace(color){var format=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;format=ColorItem.sanitizeFormat(format);this._original={color,format,valid:true};this._color=ColorItem.parse(color);if(this._color===null){this._color=(0,_color2.default)();this._original.valid=false;return}this._format=format?format:ColorItem.isHex(color)?"hex":this._color.model}},{key:"isValid",value:function isValid(){return this._original.valid===true}},{key:"setHueRatio",value:function setHueRatio(h){this.hue=(1-h)*360}},{key:"setSaturationRatio",value:function setSaturationRatio(s){this.saturation=s*100}},{key:"setValueRatio",value:function setValueRatio(v){this.value=(1-v)*100}},{key:"setAlphaRatio",value:function setAlphaRatio(a){this.alpha=1-a}},{key:"isDesaturated",value:function isDesaturated(){return this.saturation===0}},{key:"isTransparent",value:function isTransparent(){return this.alpha===0}},{key:"hasTransparency",value:function hasTransparency(){return this.hasAlpha()&&this.alpha<1}},{key:"hasAlpha",value:function hasAlpha(){return!isNaN(this.alpha)}},{key:"toObject",value:function toObject(){return new HSVAColor(this.hue,this.saturation,this.value,this.alpha)}},{key:"toHsva",value:function toHsva(){return this.toObject()}},{key:"toHsvaRatio",value:function toHsvaRatio(){return new HSVAColor(this.hue/360,this.saturation/100,this.value/100,this.alpha)}},{key:"toString",value:function toString(){return this.string()}},{key:"string",value:function string(){var format=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;format=ColorItem.sanitizeFormat(format?format:this.format);if(!format){return this._color.round().string()}if(this._color[format]===undefined){throw new Error("Unsupported color format: '"+format+"'")}var str=this._color[format]();return str.round?str.round().string():str}},{key:"equals",value:function equals(color){color=color instanceof ColorItem?color:new ColorItem(color);if(!color.isValid()||!this.isValid()){return false}return this.hue===color.hue&&this.saturation===color.saturation&&this.value===color.value&&this.alpha===color.alpha}},{key:"getClone",value:function getClone(){return new ColorItem(this._color,this.format)}},{key:"getCloneHueOnly",value:function getCloneHueOnly(){return new ColorItem([this.hue,100,100,1],this.format)}},{key:"getCloneOpaque",value:function getCloneOpaque(){return new ColorItem(this._color.alpha(1),this.format)}},{key:"toRgbString",value:function toRgbString(){return this.string("rgb")}},{key:"toHexString",value:function toHexString(){return this.string("hex")}},{key:"toHslString",value:function toHslString(){return this.string("hsl")}},{key:"isDark",value:function isDark(){return this._color.isDark()}},{key:"isLight",value:function isLight(){return this._color.isLight()}},{key:"generate",value:function generate(formula){var hues=[];if(Array.isArray(formula)){hues=formula}else if(!ColorItem.colorFormulas.hasOwnProperty(formula)){throw new Error("No color formula found with the name '"+formula+"'.")}else{hues=ColorItem.colorFormulas[formula]}var colors=[],mainColor=this._color,format=this.format;hues.forEach(function(hue){var levels=[hue?(mainColor.hue()+hue)%360:mainColor.hue(),mainColor.saturationv(),mainColor.value(),mainColor.alpha()];colors.push(new ColorItem(levels,format))});return colors}},{key:"hue",get:function get(){return this._color.hue()},set:function set(value){this._color=this._color.hue(value)}},{key:"saturation",get:function get(){return this._color.saturationv()},set:function set(value){this._color=this._color.saturationv(value)}},{key:"value",get:function get(){return this._color.value()},set:function set(value){this._color=this._color.value(value)}},{key:"alpha",get:function get(){var a=this._color.alpha();return isNaN(a)?1:a},set:function set(value){this._color=this._color.alpha(Math.round(value*100)/100)}},{key:"format",get:function get(){return this._format?this._format:this._color.model},set:function set(value){this._format=ColorItem.sanitizeFormat(value)}}],[{key:"parse",value:function parse(color){if(color instanceof _color2.default){return color}if(color instanceof ColorItem){return color._color}var format=null;if(color instanceof HSVAColor){color=[color.h,color.s,color.v,isNaN(color.a)?1:color.a]}else{color=ColorItem.sanitizeString(color)}if(color===null){return null}if(Array.isArray(color)){format="hsv"}try{return(0,_color2.default)(color,format)}catch(e){return null}}},{key:"sanitizeString",value:function sanitizeString(str){if(!(typeof str==="string"||str instanceof String)){return str}if(str.match(/^[0-9a-f]{2,}$/i)){return"#"+str}if(str.toLowerCase()==="transparent"){return"#FFFFFF00"}return str}},{key:"isHex",value:function isHex(str){if(!(typeof str==="string"||str instanceof String)){return false}return!!str.match(/^#?[0-9a-f]{2,}$/i)}},{key:"sanitizeFormat",value:function sanitizeFormat(format){switch(format){case"hex":case"hex3":case"hex4":case"hex6":case"hex8":return"hex";case"rgb":case"rgba":case"keyword":case"name":return"rgb";case"hsl":case"hsla":case"hsv":case"hsva":case"hwb":case"hwba":return"hsl";default:return""}}}]);return ColorItem}();ColorItem.colorFormulas={complementary:[180],triad:[0,120,240],tetrad:[0,90,180,270],splitcomplement:[0,72,216]};exports.default=ColorItem;exports.HSVAColor=HSVAColor;exports.ColorItem=ColorItem},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var sassVars={bar_size_short:16,base_margin:6,columns:6};var sliderSize=sassVars.bar_size_short*sassVars.columns+sassVars.base_margin*(sassVars.columns-1);exports.default={customClass:null,color:false,fallbackColor:false,format:"auto",horizontal:false,inline:false,container:false,popover:{animation:true,placement:"bottom",fallbackPlacement:"flip"},debug:false,input:"input",addon:".colorpicker-input-addon",autoInputFallback:true,useHashPrefix:true,useAlpha:true,template:'
\n
\n
\n
\n
\n \n
\n
',extensions:[{name:"preview",options:{showText:true}}],sliders:{saturation:{selector:".colorpicker-saturation",maxLeft:sliderSize,maxTop:sliderSize,callLeft:"setSaturationRatio",callTop:"setValueRatio"},hue:{selector:".colorpicker-hue",maxLeft:0,maxTop:sliderSize,callLeft:false,callTop:"setHueRatio"},alpha:{selector:".colorpicker-alpha",childSelector:".colorpicker-alpha-color",maxLeft:0,maxTop:sliderSize,callLeft:false,callTop:"setAlphaRatio"}},slidersHorz:{saturation:{selector:".colorpicker-saturation",maxLeft:sliderSize,maxTop:sliderSize,callLeft:"setSaturationRatio",callTop:"setValueRatio"},hue:{selector:".colorpicker-hue",maxLeft:sliderSize,maxTop:0,callLeft:"setHueRatio",callTop:false},alpha:{selector:".colorpicker-alpha",childSelector:".colorpicker-alpha-color",maxLeft:sliderSize,maxTop:0,callLeft:"setAlphaRatio",callTop:false}}};module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};var _createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};_classCallCheck(this,Palette);var _this=_possibleConstructorReturn(this,(Palette.__proto__||Object.getPrototypeOf(Palette)).call(this,colorpicker,_jquery2.default.extend(true,{},defaults,options)));if(!Array.isArray(_this.options.colors)&&_typeof(_this.options.colors)!=="object"){_this.options.colors=null}return _this}_createClass(Palette,[{key:"getLength",value:function getLength(){if(!this.options.colors){return 0}if(Array.isArray(this.options.colors)){return this.options.colors.length}if(_typeof(this.options.colors)==="object"){return Object.keys(this.options.colors).length}return 0}},{key:"resolveColor",value:function resolveColor(color){var realColor=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;if(this.getLength()<=0){return false}if(Array.isArray(this.options.colors)){if(this.options.colors.indexOf(color)>=0){return color}if(this.options.colors.indexOf(color.toUpperCase())>=0){return color.toUpperCase()}if(this.options.colors.indexOf(color.toLowerCase())>=0){return color.toLowerCase()}return false}if(_typeof(this.options.colors)!=="object"){return false}if(!this.options.namesAsValues||realColor){return this.getValue(color,false)}return this.getName(color,this.getName("#"+color))}},{key:"getName",value:function getName(value){var defaultValue=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;if(!(typeof value==="string")||!this.options.colors){return defaultValue}for(var name in this.options.colors){if(!this.options.colors.hasOwnProperty(name)){continue}if(this.options.colors[name].toLowerCase()===value.toLowerCase()){return name}}return defaultValue}},{key:"getValue",value:function getValue(name){var defaultValue=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;if(!(typeof name==="string")||!this.options.colors){return defaultValue}if(this.options.colors.hasOwnProperty(name)){return this.options.colors[name]}return defaultValue}}]);return Palette}(_Extension3.default);exports.default=Palette;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";module.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},function(module,exports,__webpack_require__){var cssKeywords=__webpack_require__(5);var reverseKeywords={};for(var key in cssKeywords){if(cssKeywords.hasOwnProperty(key)){reverseKeywords[cssKeywords[key]]=key}}var convert=module.exports={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};for(var model in convert){if(convert.hasOwnProperty(model)){if(!("channels"in convert[model])){throw new Error("missing channels property: "+model)}if(!("labels"in convert[model])){throw new Error("missing channel labels property: "+model)}if(convert[model].labels.length!==convert[model].channels){throw new Error("channel and label counts mismatch: "+model)}var channels=convert[model].channels;var labels=convert[model].labels;delete convert[model].channels;delete convert[model].labels;Object.defineProperty(convert[model],"channels",{value:channels});Object.defineProperty(convert[model],"labels",{value:labels})}}convert.rgb.hsl=function(rgb){var r=rgb[0]/255;var g=rgb[1]/255;var b=rgb[2]/255;var min=Math.min(r,g,b);var max=Math.max(r,g,b);var delta=max-min;var h;var s;var l;if(max===min){h=0}else if(r===max){h=(g-b)/delta}else if(g===max){h=2+(b-r)/delta}else if(b===max){h=4+(r-g)/delta}h=Math.min(h*60,360);if(h<0){h+=360}l=(min+max)/2;if(max===min){s=0}else if(l<=.5){s=delta/(max+min)}else{s=delta/(2-max-min)}return[h,s*100,l*100]};convert.rgb.hsv=function(rgb){var rdif;var gdif;var bdif;var h;var s;var r=rgb[0]/255;var g=rgb[1]/255;var b=rgb[2]/255;var v=Math.max(r,g,b);var diff=v-Math.min(r,g,b);var diffc=function(c){return(v-c)/6/diff+1/2};if(diff===0){h=s=0}else{s=diff/v;rdif=diffc(r);gdif=diffc(g);bdif=diffc(b);if(r===v){h=bdif-gdif}else if(g===v){h=1/3+rdif-bdif}else if(b===v){h=2/3+gdif-rdif}if(h<0){h+=1}else if(h>1){h-=1}}return[h*360,s*100,v*100]};convert.rgb.hwb=function(rgb){var r=rgb[0];var g=rgb[1];var b=rgb[2];var h=convert.rgb.hsl(rgb)[0];var w=1/255*Math.min(r,Math.min(g,b));b=1-1/255*Math.max(r,Math.max(g,b));return[h,w*100,b*100]};convert.rgb.cmyk=function(rgb){var r=rgb[0]/255;var g=rgb[1]/255;var b=rgb[2]/255;var c;var m;var y;var k;k=Math.min(1-r,1-g,1-b);c=(1-r-k)/(1-k)||0;m=(1-g-k)/(1-k)||0;y=(1-b-k)/(1-k)||0;return[c*100,m*100,y*100,k*100]};function comparativeDistance(x,y){return Math.pow(x[0]-y[0],2)+Math.pow(x[1]-y[1],2)+Math.pow(x[2]-y[2],2)}convert.rgb.keyword=function(rgb){var reversed=reverseKeywords[rgb];if(reversed){return reversed}var currentClosestDistance=Infinity;var currentClosestKeyword;for(var keyword in cssKeywords){if(cssKeywords.hasOwnProperty(keyword)){var value=cssKeywords[keyword];var distance=comparativeDistance(rgb,value);if(distance.04045?Math.pow((r+.055)/1.055,2.4):r/12.92;g=g>.04045?Math.pow((g+.055)/1.055,2.4):g/12.92;b=b>.04045?Math.pow((b+.055)/1.055,2.4):b/12.92;var x=r*.4124+g*.3576+b*.1805;var y=r*.2126+g*.7152+b*.0722;var z=r*.0193+g*.1192+b*.9505;return[x*100,y*100,z*100]};convert.rgb.lab=function(rgb){var xyz=convert.rgb.xyz(rgb);var x=xyz[0];var y=xyz[1];var z=xyz[2];var l;var a;var b;x/=95.047;y/=100;z/=108.883;x=x>.008856?Math.pow(x,1/3):7.787*x+16/116;y=y>.008856?Math.pow(y,1/3):7.787*y+16/116;z=z>.008856?Math.pow(z,1/3):7.787*z+16/116;l=116*y-16;a=500*(x-y);b=200*(y-z);return[l,a,b]};convert.hsl.rgb=function(hsl){var h=hsl[0]/360;var s=hsl[1]/100;var l=hsl[2]/100;var t1;var t2;var t3;var rgb;var val;if(s===0){val=l*255;return[val,val,val]}if(l<.5){t2=l*(1+s)}else{t2=l+s-l*s}t1=2*l-t2;rgb=[0,0,0];for(var i=0;i<3;i++){t3=h+1/3*-(i-1);if(t3<0){t3++}if(t3>1){t3--}if(6*t3<1){val=t1+(t2-t1)*6*t3}else if(2*t3<1){val=t2}else if(3*t3<2){val=t1+(t2-t1)*(2/3-t3)*6}else{val=t1}rgb[i]=val*255}return rgb};convert.hsl.hsv=function(hsl){var h=hsl[0];var s=hsl[1]/100;var l=hsl[2]/100;var smin=s;var lmin=Math.max(l,.01);var sv;var v;l*=2;s*=l<=1?l:2-l;smin*=lmin<=1?lmin:2-lmin;v=(l+s)/2;sv=l===0?2*smin/(lmin+smin):2*s/(l+s);return[h,sv*100,v*100]};convert.hsv.rgb=function(hsv){var h=hsv[0]/60;var s=hsv[1]/100;var v=hsv[2]/100;var hi=Math.floor(h)%6;var f=h-Math.floor(h);var p=255*v*(1-s);var q=255*v*(1-s*f);var t=255*v*(1-s*(1-f));v*=255;switch(hi){case 0:return[v,t,p];case 1:return[q,v,p];case 2:return[p,v,t];case 3:return[p,q,v];case 4:return[t,p,v];case 5:return[v,p,q]}};convert.hsv.hsl=function(hsv){var h=hsv[0];var s=hsv[1]/100;var v=hsv[2]/100;var vmin=Math.max(v,.01);var lmin;var sl;var l;l=(2-s)*v;lmin=(2-s)*vmin;sl=s*vmin;sl/=lmin<=1?lmin:2-lmin;sl=sl||0;l/=2;return[h,sl*100,l*100]};convert.hwb.rgb=function(hwb){var h=hwb[0]/360;var wh=hwb[1]/100;var bl=hwb[2]/100;var ratio=wh+bl;var i;var v;var f;var n;if(ratio>1){wh/=ratio;bl/=ratio}i=Math.floor(6*h);v=1-bl;f=6*h-i;if((i&1)!==0){f=1-f}n=wh+f*(v-wh);var r;var g;var b;switch(i){default:case 6:case 0:r=v;g=n;b=wh;break;case 1:r=n;g=v;b=wh;break;case 2:r=wh;g=v;b=n;break;case 3:r=wh;g=n;b=v;break;case 4:r=n;g=wh;b=v;break;case 5:r=v;g=wh;b=n;break}return[r*255,g*255,b*255]};convert.cmyk.rgb=function(cmyk){var c=cmyk[0]/100;var m=cmyk[1]/100;var y=cmyk[2]/100;var k=cmyk[3]/100;var r;var g;var b;r=1-Math.min(1,c*(1-k)+k);g=1-Math.min(1,m*(1-k)+k);b=1-Math.min(1,y*(1-k)+k);return[r*255,g*255,b*255]};convert.xyz.rgb=function(xyz){var x=xyz[0]/100;var y=xyz[1]/100;var z=xyz[2]/100;var r;var g;var b;r=x*3.2406+y*-1.5372+z*-.4986;g=x*-.9689+y*1.8758+z*.0415;b=x*.0557+y*-.204+z*1.057;r=r>.0031308?1.055*Math.pow(r,1/2.4)-.055:r*12.92;g=g>.0031308?1.055*Math.pow(g,1/2.4)-.055:g*12.92;b=b>.0031308?1.055*Math.pow(b,1/2.4)-.055:b*12.92;r=Math.min(Math.max(0,r),1);g=Math.min(Math.max(0,g),1);b=Math.min(Math.max(0,b),1);return[r*255,g*255,b*255]};convert.xyz.lab=function(xyz){var x=xyz[0];var y=xyz[1];var z=xyz[2];var l;var a;var b;x/=95.047;y/=100;z/=108.883;x=x>.008856?Math.pow(x,1/3):7.787*x+16/116;y=y>.008856?Math.pow(y,1/3):7.787*y+16/116;z=z>.008856?Math.pow(z,1/3):7.787*z+16/116;l=116*y-16;a=500*(x-y);b=200*(y-z);return[l,a,b]};convert.lab.xyz=function(lab){var l=lab[0];var a=lab[1];var b=lab[2];var x;var y;var z;y=(l+16)/116;x=a/500+y;z=y-b/200;var y2=Math.pow(y,3);var x2=Math.pow(x,3);var z2=Math.pow(z,3);y=y2>.008856?y2:(y-16/116)/7.787;x=x2>.008856?x2:(x-16/116)/7.787;z=z2>.008856?z2:(z-16/116)/7.787;x*=95.047;y*=100;z*=108.883;return[x,y,z]};convert.lab.lch=function(lab){var l=lab[0];var a=lab[1];var b=lab[2];var hr;var h;var c;hr=Math.atan2(b,a);h=hr*360/2/Math.PI;if(h<0){h+=360}c=Math.sqrt(a*a+b*b);return[l,c,h]};convert.lch.lab=function(lch){var l=lch[0];var c=lch[1];var h=lch[2];var a;var b;var hr;hr=h/360*2*Math.PI;a=c*Math.cos(hr);b=c*Math.sin(hr);return[l,a,b]};convert.rgb.ansi16=function(args){var r=args[0];var g=args[1];var b=args[2];var value=1 in arguments?arguments[1]:convert.rgb.hsv(args)[2];value=Math.round(value/50);if(value===0){return 30}var ansi=30+(Math.round(b/255)<<2|Math.round(g/255)<<1|Math.round(r/255));if(value===2){ansi+=60}return ansi};convert.hsv.ansi16=function(args){return convert.rgb.ansi16(convert.hsv.rgb(args),args[2])};convert.rgb.ansi256=function(args){var r=args[0];var g=args[1];var b=args[2];if(r===g&&g===b){if(r<8){return 16}if(r>248){return 231}return Math.round((r-8)/247*24)+232}var ansi=16+36*Math.round(r/255*5)+6*Math.round(g/255*5)+Math.round(b/255*5);return ansi};convert.ansi16.rgb=function(args){var color=args%10;if(color===0||color===7){if(args>50){color+=3.5}color=color/10.5*255;return[color,color,color]}var mult=(~~(args>50)+1)*.5;var r=(color&1)*mult*255;var g=(color>>1&1)*mult*255;var b=(color>>2&1)*mult*255;return[r,g,b]};convert.ansi256.rgb=function(args){if(args>=232){var c=(args-232)*10+8;return[c,c,c]}args-=16;var rem;var r=Math.floor(args/36)/5*255;var g=Math.floor((rem=args%36)/6)/5*255;var b=rem%6/5*255;return[r,g,b]};convert.rgb.hex=function(args){var integer=((Math.round(args[0])&255)<<16)+((Math.round(args[1])&255)<<8)+(Math.round(args[2])&255);var string=integer.toString(16).toUpperCase();return"000000".substring(string.length)+string};convert.hex.rgb=function(args){var match=args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!match){return[0,0,0]}var colorString=match[0];if(match[0].length===3){colorString=colorString.split("").map(function(char){return char+char}).join("")}var integer=parseInt(colorString,16);var r=integer>>16&255;var g=integer>>8&255;var b=integer&255;return[r,g,b]};convert.rgb.hcg=function(rgb){var r=rgb[0]/255;var g=rgb[1]/255;var b=rgb[2]/255;var max=Math.max(Math.max(r,g),b);var min=Math.min(Math.min(r,g),b);var chroma=max-min;var grayscale;var hue;if(chroma<1){grayscale=min/(1-chroma)}else{grayscale=0}if(chroma<=0){hue=0}else if(max===r){hue=(g-b)/chroma%6}else if(max===g){hue=2+(b-r)/chroma}else{hue=4+(r-g)/chroma+4}hue/=6;hue%=1;return[hue*360,chroma*100,grayscale*100]};convert.hsl.hcg=function(hsl){var s=hsl[1]/100;var l=hsl[2]/100;var c=1;var f=0;if(l<.5){c=2*s*l}else{c=2*s*(1-l)}if(c<1){f=(l-.5*c)/(1-c)}return[hsl[0],c*100,f*100]};convert.hsv.hcg=function(hsv){var s=hsv[1]/100;var v=hsv[2]/100;var c=s*v;var f=0;if(c<1){f=(v-c)/(1-c)}return[hsv[0],c*100,f*100]};convert.hcg.rgb=function(hcg){var h=hcg[0]/360;var c=hcg[1]/100;var g=hcg[2]/100;if(c===0){return[g*255,g*255,g*255]}var pure=[0,0,0];var hi=h%1*6;var v=hi%1;var w=1-v;var mg=0;switch(Math.floor(hi)){case 0:pure[0]=1;pure[1]=v;pure[2]=0;break;case 1:pure[0]=w;pure[1]=1;pure[2]=0;break;case 2:pure[0]=0;pure[1]=1;pure[2]=v;break;case 3:pure[0]=0;pure[1]=w;pure[2]=1;break;case 4:pure[0]=v;pure[1]=0;pure[2]=1;break;default:pure[0]=1;pure[1]=0;pure[2]=w}mg=(1-c)*g;return[(c*pure[0]+mg)*255,(c*pure[1]+mg)*255,(c*pure[2]+mg)*255]};convert.hcg.hsv=function(hcg){var c=hcg[1]/100;var g=hcg[2]/100;var v=c+g*(1-c);var f=0;if(v>0){f=c/v}return[hcg[0],f*100,v*100]};convert.hcg.hsl=function(hcg){var c=hcg[1]/100;var g=hcg[2]/100;var l=g*(1-c)+.5*c;var s=0;if(l>0&&l<.5){s=c/(2*l)}else if(l>=.5&&l<1){s=c/(2*(1-l))}return[hcg[0],s*100,l*100]};convert.hcg.hwb=function(hcg){var c=hcg[1]/100;var g=hcg[2]/100;var v=c+g*(1-c);return[hcg[0],(v-c)*100,(1-v)*100]};convert.hwb.hcg=function(hwb){var w=hwb[1]/100;var b=hwb[2]/100;var v=1-b;var c=v-w;var g=0;if(c<1){g=(v-c)/(1-c)}return[hwb[0],c*100,g*100]};convert.apple.rgb=function(apple){return[apple[0]/65535*255,apple[1]/65535*255,apple[2]/65535*255]};convert.rgb.apple=function(rgb){return[rgb[0]/255*65535,rgb[1]/255*65535,rgb[2]/255*65535]};convert.gray.rgb=function(args){return[args[0]/100*255,args[0]/100*255,args[0]/100*255]};convert.gray.hsl=convert.gray.hsv=function(args){return[0,0,args[0]]};convert.gray.hwb=function(gray){return[0,100,gray[0]]};convert.gray.cmyk=function(gray){return[0,0,0,gray[0]]};convert.gray.lab=function(gray){return[gray[0],0,0]};convert.gray.hex=function(gray){var val=Math.round(gray[0]/100*255)&255;var integer=(val<<16)+(val<<8)+val;var string=integer.toString(16).toUpperCase();return"000000".substring(string.length)+string};convert.rgb.gray=function(rgb){var val=(rgb[0]+rgb[1]+rgb[2])/3;return[val/255*100]}},function(module,exports,__webpack_require__){"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};var _Colorpicker=__webpack_require__(8);var _Colorpicker2=_interopRequireDefault(_Colorpicker);var _jquery=__webpack_require__(0);var _jquery2=_interopRequireDefault(_jquery);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var plugin="colorpicker";_jquery2.default[plugin]=_Colorpicker2.default;_jquery2.default.fn[plugin]=function(option){var fnArgs=Array.prototype.slice.call(arguments,1),isSingleElement=this.length===1,returnValue=null;var $elements=this.each(function(){var $this=(0,_jquery2.default)(this),inst=$this.data(plugin),options=(typeof option==="undefined"?"undefined":_typeof(option))==="object"?option:{};if(!inst){inst=new _Colorpicker2.default(this,options);$this.data(plugin,inst)}if(!isSingleElement){return}returnValue=$this;if(typeof option==="string"){if(option==="colorpicker"){returnValue=inst}else if(_jquery2.default.isFunction(inst[option])){returnValue=inst[option].apply(inst,fnArgs)}else{returnValue=inst[option]}}});return isSingleElement?returnValue:$elements};_jquery2.default.fn[plugin].constructor=_Colorpicker2.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};var ext=new ExtensionClass(this,config);this.extensions.push(ext);return ext}},{key:"destroy",value:function destroy(){var color=this.color;this.sliderHandler.unbind();this.inputHandler.unbind();this.popupHandler.unbind();this.colorHandler.unbind();this.addonHandler.unbind();this.pickerHandler.unbind();this.element.removeClass("colorpicker-element").removeData("colorpicker","color").off(".colorpicker");this.trigger("colorpickerDestroy",color)}},{key:"show",value:function show(e){this.popupHandler.show(e)}},{key:"hide",value:function hide(e){this.popupHandler.hide(e)}},{key:"toggle",value:function toggle(e){this.popupHandler.toggle(e)}},{key:"getValue",value:function getValue(){var defaultValue=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;var val=this.colorHandler.color;val=val instanceof _ColorItem2.default?val:defaultValue;if(val instanceof _ColorItem2.default){return val.string(this.format)}return val}},{key:"setValue",value:function setValue(val){if(this.isDisabled()){return}var ch=this.colorHandler;if(ch.hasColor()&&!!val&&ch.color.equals(val)||!ch.hasColor()&&!val){return}ch.color=val?ch.createColor(val,this.options.autoInputFallback):null;this.trigger("colorpickerChange",ch.color,val);this.update()}},{key:"update",value:function update(){if(this.colorHandler.hasColor()){this.inputHandler.update()}else{this.colorHandler.assureColor()}this.addonHandler.update();this.pickerHandler.update();this.trigger("colorpickerUpdate")}},{key:"enable",value:function enable(){this.inputHandler.enable();this.disabled=false;this.picker.removeClass("colorpicker-disabled");this.trigger("colorpickerEnable");return true}},{key:"disable",value:function disable(){this.inputHandler.disable();this.disabled=true;this.picker.addClass("colorpicker-disabled");this.trigger("colorpickerDisable");return true}},{key:"isEnabled",value:function isEnabled(){return!this.isDisabled()}},{key:"isDisabled",value:function isDisabled(){return this.disabled===true}},{key:"trigger",value:function trigger(eventName){var color=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;var value=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;this.element.trigger({type:eventName,colorpicker:this,color:color?color:this.color,value:value?value:this.getValue()})}}]);return Colorpicker}();Colorpicker.extensions=_extensions2.default;exports.default=Colorpicker;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.Palette=exports.Swatches=exports.Preview=exports.Debugger=undefined;var _Debugger=__webpack_require__(10);var _Debugger2=_interopRequireDefault(_Debugger);var _Preview=__webpack_require__(11);var _Preview2=_interopRequireDefault(_Preview);var _Swatches=__webpack_require__(12);var _Swatches2=_interopRequireDefault(_Swatches);var _Palette=__webpack_require__(4);var _Palette2=_interopRequireDefault(_Palette);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}exports.Debugger=_Debugger2.default;exports.Preview=_Preview2.default;exports.Swatches=_Swatches2.default;exports.Palette=_Palette2.default;exports.default={debugger:_Debugger2.default,preview:_Preview2.default,swatches:_Swatches2.default,palette:_Palette2.default}},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};_classCallCheck(this,Debugger);var _this=_possibleConstructorReturn(this,(Debugger.__proto__||Object.getPrototypeOf(Debugger)).call(this,colorpicker,options));_this.eventCounter=0;if(_this.colorpicker.inputHandler.hasInput()){_this.colorpicker.inputHandler.input.on("change.colorpicker-ext",_jquery2.default.proxy(_this.onChangeInput,_this))}return _this}_createClass(Debugger,[{key:"log",value:function log(eventName){var _console;for(var _len=arguments.length,args=Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key]}this.eventCounter+=1;var logMessage="#"+this.eventCounter+": Colorpicker#"+this.colorpicker.id+" ["+eventName+"]";(_console=console).debug.apply(_console,[logMessage].concat(args));this.colorpicker.element.trigger({type:"colorpickerDebug",colorpicker:this.colorpicker,color:this.color,value:null,debug:{debugger:this,eventName,logArgs:args,logMessage}})}},{key:"resolveColor",value:function resolveColor(color){var realColor=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;this.log("resolveColor()",color,realColor);return false}},{key:"onCreate",value:function onCreate(event){this.log("colorpickerCreate");return _get(Debugger.prototype.__proto__||Object.getPrototypeOf(Debugger.prototype),"onCreate",this).call(this,event)}},{key:"onDestroy",value:function onDestroy(event){this.log("colorpickerDestroy");this.eventCounter=0;if(this.colorpicker.inputHandler.hasInput()){this.colorpicker.inputHandler.input.off(".colorpicker-ext")}return _get(Debugger.prototype.__proto__||Object.getPrototypeOf(Debugger.prototype),"onDestroy",this).call(this,event)}},{key:"onUpdate",value:function onUpdate(event){this.log("colorpickerUpdate")}},{key:"onChangeInput",value:function onChangeInput(event){this.log("input:change.colorpicker",event.value,event.color)}},{key:"onChange",value:function onChange(event){this.log("colorpickerChange",event.value,event.color)}},{key:"onInvalid",value:function onInvalid(event){this.log("colorpickerInvalid",event.value,event.color)}},{key:"onHide",value:function onHide(event){this.log("colorpickerHide");this.eventCounter=0}},{key:"onShow",value:function onShow(event){this.log("colorpickerShow")}},{key:"onDisable",value:function onDisable(event){this.log("colorpickerDisable")}},{key:"onEnable",value:function onEnable(event){this.log("colorpickerEnable")}}]);return Debugger}(_Extension3.default);exports.default=Debugger;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};_classCallCheck(this,Preview);var _this=_possibleConstructorReturn(this,(Preview.__proto__||Object.getPrototypeOf(Preview)).call(this,colorpicker,_jquery2.default.extend(true,{},{template:'
',showText:true,format:colorpicker.format},options)));_this.element=(0,_jquery2.default)(_this.options.template);_this.elementInner=_this.element.find("div");return _this}_createClass(Preview,[{key:"onCreate",value:function onCreate(event){_get(Preview.prototype.__proto__||Object.getPrototypeOf(Preview.prototype),"onCreate",this).call(this,event);this.colorpicker.picker.append(this.element)}},{key:"onUpdate",value:function onUpdate(event){_get(Preview.prototype.__proto__||Object.getPrototypeOf(Preview.prototype),"onUpdate",this).call(this,event);if(!event.color){this.elementInner.css("backgroundColor",null).css("color",null).html("");return}this.elementInner.css("backgroundColor",event.color.toRgbString());if(this.options.showText){this.elementInner.html(event.color.string(this.options.format||this.colorpicker.format));if(event.color.isDark()&&event.color.alpha>.5){this.elementInner.css("color","white")}else{this.elementInner.css("color","black")}}}}]);return Preview}(_Extension3.default);exports.default=Preview;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i\n
\n
',swatchTemplate:''};var Swatches=function(_Palette){_inherits(Swatches,_Palette);function Swatches(colorpicker){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};_classCallCheck(this,Swatches);var _this=_possibleConstructorReturn(this,(Swatches.__proto__||Object.getPrototypeOf(Swatches)).call(this,colorpicker,_jquery2.default.extend(true,{},defaults,options)));_this.element=null;return _this}_createClass(Swatches,[{key:"isEnabled",value:function isEnabled(){return this.getLength()>0}},{key:"onCreate",value:function onCreate(event){_get(Swatches.prototype.__proto__||Object.getPrototypeOf(Swatches.prototype),"onCreate",this).call(this,event);if(!this.isEnabled()){return}this.element=(0,_jquery2.default)(this.options.barTemplate);this.load();this.colorpicker.picker.append(this.element)}},{key:"load",value:function load(){var _this2=this;var colorpicker=this.colorpicker,swatchContainer=this.element.find(".colorpicker-swatches--inner"),isAliased=this.options.namesAsValues===true&&!Array.isArray(this.colors);swatchContainer.empty();_jquery2.default.each(this.colors,function(name,value){var $swatch=(0,_jquery2.default)(_this2.options.swatchTemplate).attr("data-name",name).attr("data-value",value).attr("title",isAliased?name+": "+value:value).on("mousedown.colorpicker touchstart.colorpicker",function(e){var $sw=(0,_jquery2.default)(this);colorpicker.setValue(isAliased?$sw.attr("data-name"):$sw.attr("data-value"))});$swatch.find(".colorpicker-swatch--inner").css("background-color",value);swatchContainer.append($swatch)});swatchContainer.append((0,_jquery2.default)(''))}}]);return Swatches}(_Palette3.default);exports.default=Swatches;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i0}},{key:"onClickingInside",value:function onClickingInside(e){this.clicking=this.isClickingInside(e)}},{key:"createPopover",value:function createPopover(){var cp=this.colorpicker;this.popoverTarget=this.hasAddon?this.addon:this.input;cp.picker.addClass("colorpicker-bs-popover-content");this.popoverTarget.popover(_jquery2.default.extend(true,{},_options2.default.popover,cp.options.popover,{trigger:"manual",content:cp.picker,html:true}));this.popoverTip=(0,_jquery2.default)(this.popoverTarget.popover("getTipElement").data("bs.popover").tip);this.popoverTip.addClass("colorpicker-bs-popover");this.popoverTarget.on("shown.bs.popover",_jquery2.default.proxy(this.fireShow,this));this.popoverTarget.on("hidden.bs.popover",_jquery2.default.proxy(this.fireHide,this))}},{key:"reposition",value:function reposition(e){if(this.popoverTarget&&this.isVisible()){this.popoverTarget.popover("update")}}},{key:"toggle",value:function toggle(e){if(this.isVisible()){this.hide(e)}else{this.show(e)}}},{key:"show",value:function show(e){if(this.isVisible()||this.showing||this.hidding){return}this.showing=true;this.hidding=false;this.clicking=false;var cp=this.colorpicker;cp.lastEvent.alias="show";cp.lastEvent.e=e;if(e&&(!this.hasInput||this.input.attr("type")==="color")&&e&&e.preventDefault){e.stopPropagation();e.preventDefault()}if(this.isPopover){(0,_jquery2.default)(this.root).on("resize.colorpicker",_jquery2.default.proxy(this.reposition,this))}cp.picker.addClass("colorpicker-visible").removeClass("colorpicker-hidden");if(this.popoverTarget){this.popoverTarget.popover("show")}else{this.fireShow()}}},{key:"fireShow",value:function fireShow(){this.hidding=false;this.showing=false;if(this.isPopover){(0,_jquery2.default)(this.root.document).on("mousedown.colorpicker touchstart.colorpicker",_jquery2.default.proxy(this.hide,this));(0,_jquery2.default)(this.root.document).on("mousedown.colorpicker touchstart.colorpicker",_jquery2.default.proxy(this.onClickingInside,this))}this.colorpicker.trigger("colorpickerShow")}},{key:"hide",value:function hide(e){if(this.isHidden()||this.showing||this.hidding){return}var cp=this.colorpicker,clicking=this.clicking||this.isClickingInside(e);this.hidding=true;this.showing=false;this.clicking=false;cp.lastEvent.alias="hide";cp.lastEvent.e=e;if(clicking){this.hidding=false;return}if(this.popoverTarget){this.popoverTarget.popover("hide")}else{this.fireHide()}}},{key:"fireHide",value:function fireHide(){this.hidding=false;this.showing=false;var cp=this.colorpicker;cp.picker.addClass("colorpicker-hidden").removeClass("colorpicker-visible");(0,_jquery2.default)(this.root).off("resize.colorpicker",_jquery2.default.proxy(this.reposition,this));(0,_jquery2.default)(this.root.document).off("mousedown.colorpicker touchstart.colorpicker",_jquery2.default.proxy(this.hide,this));(0,_jquery2.default)(this.root.document).off("mousedown.colorpicker touchstart.colorpicker",_jquery2.default.proxy(this.onClickingInside,this));cp.trigger("colorpickerHide")}},{key:"focus",value:function focus(){if(this.hasAddon){return this.addon.focus()}if(this.hasInput){return this.input.focus()}return false}},{key:"isVisible",value:function isVisible(){return this.colorpicker.picker.hasClass("colorpicker-visible")&&!this.colorpicker.picker.hasClass("colorpicker-hidden")}},{key:"isHidden",value:function isHidden(){return this.colorpicker.picker.hasClass("colorpicker-hidden")&&!this.colorpicker.picker.hasClass("colorpicker-visible")}},{key:"input",get:function get(){return this.colorpicker.inputHandler.input}},{key:"hasInput",get:function get(){return this.colorpicker.inputHandler.hasInput()}},{key:"addon",get:function get(){return this.colorpicker.addonHandler.addon}},{key:"hasAddon",get:function get(){return this.colorpicker.addonHandler.hasAddon()}},{key:"isPopover",get:function get(){return!this.colorpicker.options.inline&&!!this.popoverTip}}]);return PopupHandler}();exports.default=PopupHandler;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i0&&arguments[0]!==undefined?arguments[0]:null;val=val?val:this.colorpicker.colorHandler.getColorString();if(!val){return""}val=this.colorpicker.colorHandler.resolveColorDelegate(val,false);if(this.colorpicker.options.useHashPrefix===false){val=val.replace(/^#/g,"")}return val}},{key:"hasInput",value:function hasInput(){return this.input!==false}},{key:"isEnabled",value:function isEnabled(){return this.hasInput()&&!this.isDisabled()}},{key:"isDisabled",value:function isDisabled(){return this.hasInput()&&this.input.prop("disabled")===true}},{key:"disable",value:function disable(){if(this.hasInput()){this.input.prop("disabled",true)}}},{key:"enable",value:function enable(){if(this.hasInput()){this.input.prop("disabled",false)}}},{key:"update",value:function update(){if(!this.hasInput()){return}if(this.colorpicker.options.autoInputFallback===false&&this.colorpicker.colorHandler.isInvalidColor()){return}this.setValue(this.getFormattedColor())}},{key:"onchange",value:function onchange(e){this.colorpicker.lastEvent.alias="input.change";this.colorpicker.lastEvent.e=e;var val=this.getValue();if(val!==e.value){this.colorpicker.setValue(val)}}},{key:"onkeyup",value:function onkeyup(e){this.colorpicker.lastEvent.alias="input.keyup";this.colorpicker.lastEvent.e=e;var val=this.getValue();if(val!==e.value){this.colorpicker.setValue(val)}}}]);return InputHandler}();exports.default=InputHandler;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";var colorString=__webpack_require__(17);var convert=__webpack_require__(20);var _slice=[].slice;var skippedModels=["keyword","gray","hex"];var hashedModelKeys={};Object.keys(convert).forEach(function(model){hashedModelKeys[_slice.call(convert[model].labels).sort().join("")]=model});var limiters={};function Color(obj,model){if(!(this instanceof Color)){return new Color(obj,model)}if(model&&model in skippedModels){model=null}if(model&&!(model in convert)){throw new Error("Unknown model: "+model)}var i;var channels;if(obj==null){this.model="rgb";this.color=[0,0,0];this.valpha=1}else if(obj instanceof Color){this.model=obj.model;this.color=obj.color.slice();this.valpha=obj.valpha}else if(typeof obj==="string"){var result=colorString.get(obj);if(result===null){throw new Error("Unable to parse color from string: "+obj)}this.model=result.model;channels=convert[this.model].channels;this.color=result.value.slice(0,channels);this.valpha=typeof result.value[channels]==="number"?result.value[channels]:1}else if(obj.length){this.model=model||"rgb";channels=convert[this.model].channels;var newArr=_slice.call(obj,0,channels);this.color=zeroArray(newArr,channels);this.valpha=typeof obj[channels]==="number"?obj[channels]:1}else if(typeof obj==="number"){obj&=16777215;this.model="rgb";this.color=[obj>>16&255,obj>>8&255,obj&255];this.valpha=1}else{this.valpha=1;var keys=Object.keys(obj);if("alpha"in obj){keys.splice(keys.indexOf("alpha"),1);this.valpha=typeof obj.alpha==="number"?obj.alpha:0}var hashedKeys=keys.sort().join("");if(!(hashedKeys in hashedModelKeys)){throw new Error("Unable to parse color from object: "+JSON.stringify(obj))}this.model=hashedModelKeys[hashedKeys];var labels=convert[this.model].labels;var color=[];for(i=0;ilum2){return(lum1+.05)/(lum2+.05)}return(lum2+.05)/(lum1+.05)},level:function(color2){var contrastRatio=this.contrast(color2);if(contrastRatio>=7.1){return"AAA"}return contrastRatio>=4.5?"AA":""},isDark:function(){var rgb=this.rgb().color;var yiq=(rgb[0]*299+rgb[1]*587+rgb[2]*114)/1e3;return yiq<128},isLight:function(){return!this.isDark()},negate:function(){var rgb=this.rgb();for(var i=0;i<3;i++){rgb.color[i]=255-rgb.color[i]}return rgb},lighten:function(ratio){var hsl=this.hsl();hsl.color[2]+=hsl.color[2]*ratio;return hsl},darken:function(ratio){var hsl=this.hsl();hsl.color[2]-=hsl.color[2]*ratio;return hsl},saturate:function(ratio){var hsl=this.hsl();hsl.color[1]+=hsl.color[1]*ratio;return hsl},desaturate:function(ratio){var hsl=this.hsl();hsl.color[1]-=hsl.color[1]*ratio;return hsl},whiten:function(ratio){var hwb=this.hwb();hwb.color[1]+=hwb.color[1]*ratio;return hwb},blacken:function(ratio){var hwb=this.hwb();hwb.color[2]+=hwb.color[2]*ratio;return hwb},grayscale:function(){var rgb=this.rgb().color;var val=rgb[0]*.3+rgb[1]*.59+rgb[2]*.11;return Color.rgb(val,val,val)},fade:function(ratio){return this.alpha(this.valpha-this.valpha*ratio)},opaquer:function(ratio){return this.alpha(this.valpha+this.valpha*ratio)},rotate:function(degrees){var hsl=this.hsl();var hue=hsl.color[0];hue=(hue+degrees)%360;hue=hue<0?360+hue:hue;hsl.color[0]=hue;return hsl},mix:function(mixinColor,weight){if(!mixinColor||!mixinColor.rgb){throw new Error('Argument to "mix" was not a Color instance, but rather an instance of '+typeof mixinColor)}var color1=mixinColor.rgb();var color2=this.rgb();var p=weight===undefined?.5:weight;var w=2*p-1;var a=color1.alpha()-color2.alpha();var w1=((w*a===-1?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;return Color.rgb(w1*color1.red()+w2*color2.red(),w1*color1.green()+w2*color2.green(),w1*color1.blue()+w2*color2.blue(),color1.alpha()*p+color2.alpha()*(1-p))}};Object.keys(convert).forEach(function(model){if(skippedModels.indexOf(model)!==-1){return}var channels=convert[model].channels;Color.prototype[model]=function(){if(this.model===model){return new Color(this)}if(arguments.length){return new Color(arguments,model)}var newAlpha=typeof arguments[channels]==="number"?channels:this.valpha;return new Color(assertArray(convert[this.model][model].raw(this.color)).concat(newAlpha),model)};Color[model]=function(color){if(typeof color==="number"){color=zeroArray(_slice.call(arguments),channels)}return new Color(color,model)}});function roundTo(num,places){return Number(num.toFixed(places))}function roundToPlace(places){return function(num){return roundTo(num,places)}}function getset(model,channel,modifier){model=Array.isArray(model)?model:[model];model.forEach(function(m){(limiters[m]||(limiters[m]=[]))[channel]=modifier});model=model[0];return function(val){var result;if(arguments.length){if(modifier){val=modifier(val)}result=this[model]();result.color[channel]=val;return result}result=this[model]().color[channel];if(modifier){result=modifier(result)}return result}}function maxfn(max){return function(v){return Math.max(0,Math.min(max,v))}}function assertArray(val){return Array.isArray(val)?val:[val]}function zeroArray(arr,length){for(var i=0;i=4&&hwba[3]!==1){a=", "+hwba[3]}return"hwb("+hwba[0]+", "+hwba[1]+"%, "+hwba[2]+"%"+a+")"};cs.to.keyword=function(rgb){return reverseNames[rgb.slice(0,3)]};function clamp(num,min,max){return Math.min(Math.max(min,num),max)}function hexDouble(num){var str=num.toString(16).toUpperCase();return str.length<2?"0"+str:str}},function(module,exports,__webpack_require__){"use strict";var isArrayish=__webpack_require__(19);var concat=Array.prototype.concat;var slice=Array.prototype.slice;var swizzle=module.exports=function swizzle(args){var results=[];for(var i=0,len=args.length;i=0&&obj.splice instanceof Function}},function(module,exports,__webpack_require__){var conversions=__webpack_require__(6);var route=__webpack_require__(21);var convert={};var models=Object.keys(conversions);function wrapRaw(fn){var wrappedFn=function(args){if(args===undefined||args===null){return args}if(arguments.length>1){args=Array.prototype.slice.call(arguments)}return fn(args)};if("conversion"in fn){wrappedFn.conversion=fn.conversion}return wrappedFn}function wrapRounded(fn){var wrappedFn=function(args){if(args===undefined||args===null){return args}if(arguments.length>1){args=Array.prototype.slice.call(arguments)}var result=fn(args);if(typeof result==="object"){for(var len=result.length,i=0;i1&&arguments[1]!==undefined?arguments[1]:true;var color=new _ColorItem2.default(this.resolveColorDelegate(val),this.format);if(!color.isValid()){if(fallbackOnInvalid){color=this.getFallbackColor()}this.colorpicker.trigger("colorpickerInvalid",color,val)}if(!this.isAlphaEnabled()){color.alpha=1}return color}},{key:"getFallbackColor",value:function getFallbackColor(){if(this.fallback&&this.fallback===this.color){return this.color}var fallback=this.resolveColorDelegate(this.fallback);var color=new _ColorItem2.default(fallback,this.format);if(!color.isValid()){console.warn("The fallback color is invalid. Falling back to the previous color or black if any.");return this.color?this.color:new _ColorItem2.default("#000000",this.format)}return color}},{key:"assureColor",value:function assureColor(){if(!this.hasColor()){this.color=this.getFallbackColor()}return this.color}},{key:"resolveColorDelegate",value:function resolveColorDelegate(color){var realColor=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;var extResolvedColor=false;_jquery2.default.each(this.colorpicker.extensions,function(name,ext){if(extResolvedColor!==false){return}extResolvedColor=ext.resolveColor(color,realColor)});return extResolvedColor?extResolvedColor:color}},{key:"isInvalidColor",value:function isInvalidColor(){return!this.hasColor()||!this.color.isValid()}},{key:"isAlphaEnabled",value:function isAlphaEnabled(){return this.colorpicker.options.useAlpha!==false}},{key:"hasColor",value:function hasColor(){return this.color instanceof _ColorItem2.default}},{key:"fallback",get:function get(){return this.colorpicker.options.fallbackColor?this.colorpicker.options.fallbackColor:this.hasColor()?this.color:null}},{key:"format",get:function get(){if(this.colorpicker.options.format){return this.colorpicker.options.format}if(this.hasColor()&&this.color.hasTransparency()&&this.color.format.match(/^hex/)){return this.isAlphaEnabled()?"rgba":"hex"}if(this.hasColor()){return this.color.format}return"rgb"}},{key:"color",get:function get(){return this.colorpicker.element.data("color")},set:function set(value){this.colorpicker.element.data("color",value);if(value instanceof _ColorItem2.default&&this.colorpicker.options.format==="auto"){this.colorpicker.options.format=this.color.format}}}]);return ColorHandler}();exports.default=ColorHandler;module.exports=exports.default},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i0){icn.css(styles)}else{this.addon.css(styles)}}}]);return AddonHandler}();exports.default=AddonHandler;module.exports=exports.default}])}); -//# sourceMappingURL=bootstrap-colorpicker.min.js.map \ No newline at end of file diff --git a/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE b/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE deleted file mode 100644 index 31e23cd1..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2015 The authors of Bootstrap Switch - -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. diff --git a/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE.txt b/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE.txt deleted file mode 100644 index 31e23cd1..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2015 The authors of Bootstrap Switch - -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. diff --git a/hal-core/resources/web/js/lib/bootstrap-switch.js b/hal-core/resources/web/js/lib/bootstrap-switch.js deleted file mode 100644 index 511f08fa..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-switch.js +++ /dev/null @@ -1,784 +0,0 @@ -/** - * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches. - * - * @version v3.3.4 - * @homepage https://bttstrp.github.io/bootstrap-switch - * @author Mattia Larentis (http://larentis.eu) - * @license Apache-2.0 - */ - -(function (global, factory) { - if (typeof define === "function" && define.amd) { - define(['jquery'], factory); - } else if (typeof exports !== "undefined") { - factory(require('jquery')); - } else { - var mod = { - exports: {} - }; - factory(global.jquery); - global.bootstrapSwitch = mod.exports; - } -})(this, function (_jquery) { - 'use strict'; - - var _jquery2 = _interopRequireDefault(_jquery); - - function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : { - default: obj - }; - } - - var _extends = Object.assign || function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target; - }; - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - - var _createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - var $ = _jquery2.default || window.jQuery || window.$; - - var BootstrapSwitch = function () { - function BootstrapSwitch(element) { - var _this = this; - - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, BootstrapSwitch); - - this.$element = $(element); - this.options = $.extend({}, $.fn.bootstrapSwitch.defaults, this._getElementOptions(), options); - this.prevOptions = {}; - this.$wrapper = $('
', { - class: function _class() { - var classes = []; - classes.push(_this.options.state ? 'on' : 'off'); - if (_this.options.size) { - classes.push(_this.options.size); - } - if (_this.options.disabled) { - classes.push('disabled'); - } - if (_this.options.readonly) { - classes.push('readonly'); - } - if (_this.options.indeterminate) { - classes.push('indeterminate'); - } - if (_this.options.inverse) { - classes.push('inverse'); - } - if (_this.$element.attr('id')) { - classes.push('id-' + _this.$element.attr('id')); - } - return classes.map(_this._getClass.bind(_this)).concat([_this.options.baseClass], _this._getClasses(_this.options.wrapperClass)).join(' '); - } - }); - this.$container = $('
', { class: this._getClass('container') }); - this.$on = $('', { - html: this.options.onText, - class: this._getClass('handle-on') + ' ' + this._getClass(this.options.onColor) - }); - this.$off = $('', { - html: this.options.offText, - class: this._getClass('handle-off') + ' ' + this._getClass(this.options.offColor) - }); - this.$label = $('', { - html: this.options.labelText, - class: this._getClass('label') - }); - - this.$element.on('init.bootstrapSwitch', this.options.onInit.bind(this, element)); - this.$element.on('switchChange.bootstrapSwitch', function () { - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - if (_this.options.onSwitchChange.apply(element, args) === false) { - if (_this.$element.is(':radio')) { - $('[name="' + _this.$element.attr('name') + '"]').trigger('previousState.bootstrapSwitch', true); - } else { - _this.$element.trigger('previousState.bootstrapSwitch', true); - } - } - }); - - this.$container = this.$element.wrap(this.$container).parent(); - this.$wrapper = this.$container.wrap(this.$wrapper).parent(); - this.$element.before(this.options.inverse ? this.$off : this.$on).before(this.$label).before(this.options.inverse ? this.$on : this.$off); - - if (this.options.indeterminate) { - this.$element.prop('indeterminate', true); - } - - this._init(); - this._elementHandlers(); - this._handleHandlers(); - this._labelHandlers(); - this._formHandler(); - this._externalLabelHandler(); - this.$element.trigger('init.bootstrapSwitch', this.options.state); - } - - _createClass(BootstrapSwitch, [{ - key: 'setPrevOptions', - value: function setPrevOptions() { - this.prevOptions = _extends({}, this.options); - } - }, { - key: 'state', - value: function state(value, skip) { - if (typeof value === 'undefined') { - return this.options.state; - } - if (this.options.disabled || this.options.readonly || this.options.state && !this.options.radioAllOff && this.$element.is(':radio')) { - return this.$element; - } - if (this.$element.is(':radio')) { - $('[name="' + this.$element.attr('name') + '"]').trigger('setPreviousOptions.bootstrapSwitch'); - } else { - this.$element.trigger('setPreviousOptions.bootstrapSwitch'); - } - if (this.options.indeterminate) { - this.indeterminate(false); - } - this.$element.prop('checked', Boolean(value)).trigger('change.bootstrapSwitch', skip); - return this.$element; - } - }, { - key: 'toggleState', - value: function toggleState(skip) { - if (this.options.disabled || this.options.readonly) { - return this.$element; - } - if (this.options.indeterminate) { - this.indeterminate(false); - return this.state(true); - } else { - return this.$element.prop('checked', !this.options.state).trigger('change.bootstrapSwitch', skip); - } - } - }, { - key: 'size', - value: function size(value) { - if (typeof value === 'undefined') { - return this.options.size; - } - if (this.options.size != null) { - this.$wrapper.removeClass(this._getClass(this.options.size)); - } - if (value) { - this.$wrapper.addClass(this._getClass(value)); - } - this._width(); - this._containerPosition(); - this.options.size = value; - return this.$element; - } - }, { - key: 'animate', - value: function animate(value) { - if (typeof value === 'undefined') { - return this.options.animate; - } - if (this.options.animate === Boolean(value)) { - return this.$element; - } - return this.toggleAnimate(); - } - }, { - key: 'toggleAnimate', - value: function toggleAnimate() { - this.options.animate = !this.options.animate; - this.$wrapper.toggleClass(this._getClass('animate')); - return this.$element; - } - }, { - key: 'disabled', - value: function disabled(value) { - if (typeof value === 'undefined') { - return this.options.disabled; - } - if (this.options.disabled === Boolean(value)) { - return this.$element; - } - return this.toggleDisabled(); - } - }, { - key: 'toggleDisabled', - value: function toggleDisabled() { - this.options.disabled = !this.options.disabled; - this.$element.prop('disabled', this.options.disabled); - this.$wrapper.toggleClass(this._getClass('disabled')); - return this.$element; - } - }, { - key: 'readonly', - value: function readonly(value) { - if (typeof value === 'undefined') { - return this.options.readonly; - } - if (this.options.readonly === Boolean(value)) { - return this.$element; - } - return this.toggleReadonly(); - } - }, { - key: 'toggleReadonly', - value: function toggleReadonly() { - this.options.readonly = !this.options.readonly; - this.$element.prop('readonly', this.options.readonly); - this.$wrapper.toggleClass(this._getClass('readonly')); - return this.$element; - } - }, { - key: 'indeterminate', - value: function indeterminate(value) { - if (typeof value === 'undefined') { - return this.options.indeterminate; - } - if (this.options.indeterminate === Boolean(value)) { - return this.$element; - } - return this.toggleIndeterminate(); - } - }, { - key: 'toggleIndeterminate', - value: function toggleIndeterminate() { - this.options.indeterminate = !this.options.indeterminate; - this.$element.prop('indeterminate', this.options.indeterminate); - this.$wrapper.toggleClass(this._getClass('indeterminate')); - this._containerPosition(); - return this.$element; - } - }, { - key: 'inverse', - value: function inverse(value) { - if (typeof value === 'undefined') { - return this.options.inverse; - } - if (this.options.inverse === Boolean(value)) { - return this.$element; - } - return this.toggleInverse(); - } - }, { - key: 'toggleInverse', - value: function toggleInverse() { - this.$wrapper.toggleClass(this._getClass('inverse')); - var $on = this.$on.clone(true); - var $off = this.$off.clone(true); - this.$on.replaceWith($off); - this.$off.replaceWith($on); - this.$on = $off; - this.$off = $on; - this.options.inverse = !this.options.inverse; - return this.$element; - } - }, { - key: 'onColor', - value: function onColor(value) { - if (typeof value === 'undefined') { - return this.options.onColor; - } - if (this.options.onColor) { - this.$on.removeClass(this._getClass(this.options.onColor)); - } - this.$on.addClass(this._getClass(value)); - this.options.onColor = value; - return this.$element; - } - }, { - key: 'offColor', - value: function offColor(value) { - if (typeof value === 'undefined') { - return this.options.offColor; - } - if (this.options.offColor) { - this.$off.removeClass(this._getClass(this.options.offColor)); - } - this.$off.addClass(this._getClass(value)); - this.options.offColor = value; - return this.$element; - } - }, { - key: 'onText', - value: function onText(value) { - if (typeof value === 'undefined') { - return this.options.onText; - } - this.$on.html(value); - this._width(); - this._containerPosition(); - this.options.onText = value; - return this.$element; - } - }, { - key: 'offText', - value: function offText(value) { - if (typeof value === 'undefined') { - return this.options.offText; - } - this.$off.html(value); - this._width(); - this._containerPosition(); - this.options.offText = value; - return this.$element; - } - }, { - key: 'labelText', - value: function labelText(value) { - if (typeof value === 'undefined') { - return this.options.labelText; - } - this.$label.html(value); - this._width(); - this.options.labelText = value; - return this.$element; - } - }, { - key: 'handleWidth', - value: function handleWidth(value) { - if (typeof value === 'undefined') { - return this.options.handleWidth; - } - this.options.handleWidth = value; - this._width(); - this._containerPosition(); - return this.$element; - } - }, { - key: 'labelWidth', - value: function labelWidth(value) { - if (typeof value === 'undefined') { - return this.options.labelWidth; - } - this.options.labelWidth = value; - this._width(); - this._containerPosition(); - return this.$element; - } - }, { - key: 'baseClass', - value: function baseClass(value) { - return this.options.baseClass; - } - }, { - key: 'wrapperClass', - value: function wrapperClass(value) { - if (typeof value === 'undefined') { - return this.options.wrapperClass; - } - if (!value) { - value = $.fn.bootstrapSwitch.defaults.wrapperClass; - } - this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(' ')); - this.$wrapper.addClass(this._getClasses(value).join(' ')); - this.options.wrapperClass = value; - return this.$element; - } - }, { - key: 'radioAllOff', - value: function radioAllOff(value) { - if (typeof value === 'undefined') { - return this.options.radioAllOff; - } - var val = Boolean(value); - if (this.options.radioAllOff === val) { - return this.$element; - } - this.options.radioAllOff = val; - return this.$element; - } - }, { - key: 'onInit', - value: function onInit(value) { - if (typeof value === 'undefined') { - return this.options.onInit; - } - if (!value) { - value = $.fn.bootstrapSwitch.defaults.onInit; - } - this.options.onInit = value; - return this.$element; - } - }, { - key: 'onSwitchChange', - value: function onSwitchChange(value) { - if (typeof value === 'undefined') { - return this.options.onSwitchChange; - } - if (!value) { - value = $.fn.bootstrapSwitch.defaults.onSwitchChange; - } - this.options.onSwitchChange = value; - return this.$element; - } - }, { - key: 'destroy', - value: function destroy() { - var $form = this.$element.closest('form'); - if ($form.length) { - $form.off('reset.bootstrapSwitch').removeData('bootstrap-switch'); - } - this.$container.children().not(this.$element).remove(); - this.$element.unwrap().unwrap().off('.bootstrapSwitch').removeData('bootstrap-switch'); - return this.$element; - } - }, { - key: '_getElementOptions', - value: function _getElementOptions() { - return { - state: this.$element.is(':checked'), - size: this.$element.data('size'), - animate: this.$element.data('animate'), - disabled: this.$element.is(':disabled'), - readonly: this.$element.is('[readonly]'), - indeterminate: this.$element.data('indeterminate'), - inverse: this.$element.data('inverse'), - radioAllOff: this.$element.data('radio-all-off'), - onColor: this.$element.data('on-color'), - offColor: this.$element.data('off-color'), - onText: this.$element.data('on-text'), - offText: this.$element.data('off-text'), - labelText: this.$element.data('label-text'), - handleWidth: this.$element.data('handle-width'), - labelWidth: this.$element.data('label-width'), - baseClass: this.$element.data('base-class'), - wrapperClass: this.$element.data('wrapper-class') - }; - } - }, { - key: '_width', - value: function _width() { - var _this2 = this; - - var $handles = this.$on.add(this.$off).add(this.$label).css('width', ''); - var handleWidth = this.options.handleWidth === 'auto' ? Math.round(Math.max(this.$on.width(), this.$off.width())) : this.options.handleWidth; - $handles.width(handleWidth); - this.$label.width(function (index, width) { - if (_this2.options.labelWidth !== 'auto') { - return _this2.options.labelWidth; - } - if (width < handleWidth) { - return handleWidth; - } - return width; - }); - this._handleWidth = this.$on.outerWidth(); - this._labelWidth = this.$label.outerWidth(); - this.$container.width(this._handleWidth * 2 + this._labelWidth); - return this.$wrapper.width(this._handleWidth + this._labelWidth); - } - }, { - key: '_containerPosition', - value: function _containerPosition() { - var _this3 = this; - - var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.state; - var callback = arguments[1]; - - this.$container.css('margin-left', function () { - var values = [0, '-' + _this3._handleWidth + 'px']; - if (_this3.options.indeterminate) { - return '-' + _this3._handleWidth / 2 + 'px'; - } - if (state) { - if (_this3.options.inverse) { - return values[1]; - } else { - return values[0]; - } - } else { - if (_this3.options.inverse) { - return values[0]; - } else { - return values[1]; - } - } - }); - } - }, { - key: '_init', - value: function _init() { - var _this4 = this; - - var init = function init() { - _this4.setPrevOptions(); - _this4._width(); - _this4._containerPosition(); - setTimeout(function () { - if (_this4.options.animate) { - return _this4.$wrapper.addClass(_this4._getClass('animate')); - } - }, 50); - }; - if (this.$wrapper.is(':visible')) { - init(); - return; - } - var initInterval = window.setInterval(function () { - if (_this4.$wrapper.is(':visible')) { - init(); - return window.clearInterval(initInterval); - } - }, 50); - } - }, { - key: '_elementHandlers', - value: function _elementHandlers() { - var _this5 = this; - - return this.$element.on({ - 'setPreviousOptions.bootstrapSwitch': this.setPrevOptions.bind(this), - - 'previousState.bootstrapSwitch': function previousStateBootstrapSwitch() { - _this5.options = _this5.prevOptions; - if (_this5.options.indeterminate) { - _this5.$wrapper.addClass(_this5._getClass('indeterminate')); - } - _this5.$element.prop('checked', _this5.options.state).trigger('change.bootstrapSwitch', true); - }, - - 'change.bootstrapSwitch': function changeBootstrapSwitch(event, skip) { - event.preventDefault(); - event.stopImmediatePropagation(); - var state = _this5.$element.is(':checked'); - _this5._containerPosition(state); - if (state === _this5.options.state) { - return; - } - _this5.options.state = state; - _this5.$wrapper.toggleClass(_this5._getClass('off')).toggleClass(_this5._getClass('on')); - if (!skip) { - if (_this5.$element.is(':radio')) { - $('[name="' + _this5.$element.attr('name') + '"]').not(_this5.$element).prop('checked', false).trigger('change.bootstrapSwitch', true); - } - _this5.$element.trigger('switchChange.bootstrapSwitch', [state]); - } - }, - - 'focus.bootstrapSwitch': function focusBootstrapSwitch(event) { - event.preventDefault(); - _this5.$wrapper.addClass(_this5._getClass('focused')); - }, - - 'blur.bootstrapSwitch': function blurBootstrapSwitch(event) { - event.preventDefault(); - _this5.$wrapper.removeClass(_this5._getClass('focused')); - }, - - 'keydown.bootstrapSwitch': function keydownBootstrapSwitch(event) { - if (!event.which || _this5.options.disabled || _this5.options.readonly) { - return; - } - if (event.which === 37 || event.which === 39) { - event.preventDefault(); - event.stopImmediatePropagation(); - _this5.state(event.which === 39); - } - } - }); - } - }, { - key: '_handleHandlers', - value: function _handleHandlers() { - var _this6 = this; - - this.$on.on('click.bootstrapSwitch', function (event) { - event.preventDefault(); - event.stopPropagation(); - _this6.state(false); - return _this6.$element.trigger('focus.bootstrapSwitch'); - }); - return this.$off.on('click.bootstrapSwitch', function (event) { - event.preventDefault(); - event.stopPropagation(); - _this6.state(true); - return _this6.$element.trigger('focus.bootstrapSwitch'); - }); - } - }, { - key: '_labelHandlers', - value: function _labelHandlers() { - var _this7 = this; - - var handlers = { - click: function click(event) { - event.stopPropagation(); - }, - - - 'mousedown.bootstrapSwitch touchstart.bootstrapSwitch': function mousedownBootstrapSwitchTouchstartBootstrapSwitch(event) { - if (_this7._dragStart || _this7.options.disabled || _this7.options.readonly) { - return; - } - event.preventDefault(); - event.stopPropagation(); - _this7._dragStart = (event.pageX || event.originalEvent.touches[0].pageX) - parseInt(_this7.$container.css('margin-left'), 10); - if (_this7.options.animate) { - _this7.$wrapper.removeClass(_this7._getClass('animate')); - } - _this7.$element.trigger('focus.bootstrapSwitch'); - }, - - 'mousemove.bootstrapSwitch touchmove.bootstrapSwitch': function mousemoveBootstrapSwitchTouchmoveBootstrapSwitch(event) { - if (_this7._dragStart == null) { - return; - } - var difference = (event.pageX || event.originalEvent.touches[0].pageX) - _this7._dragStart; - event.preventDefault(); - if (difference < -_this7._handleWidth || difference > 0) { - return; - } - _this7._dragEnd = difference; - _this7.$container.css('margin-left', _this7._dragEnd + 'px'); - }, - - 'mouseup.bootstrapSwitch touchend.bootstrapSwitch': function mouseupBootstrapSwitchTouchendBootstrapSwitch(event) { - if (!_this7._dragStart) { - return; - } - event.preventDefault(); - if (_this7.options.animate) { - _this7.$wrapper.addClass(_this7._getClass('animate')); - } - if (_this7._dragEnd) { - var state = _this7._dragEnd > -(_this7._handleWidth / 2); - _this7._dragEnd = false; - _this7.state(_this7.options.inverse ? !state : state); - } else { - _this7.state(!_this7.options.state); - } - _this7._dragStart = false; - }, - - 'mouseleave.bootstrapSwitch': function mouseleaveBootstrapSwitch() { - _this7.$label.trigger('mouseup.bootstrapSwitch'); - } - }; - this.$label.on(handlers); - } - }, { - key: '_externalLabelHandler', - value: function _externalLabelHandler() { - var _this8 = this; - - var $externalLabel = this.$element.closest('label'); - $externalLabel.on('click', function (event) { - event.preventDefault(); - event.stopImmediatePropagation(); - if (event.target === $externalLabel[0]) { - _this8.toggleState(); - } - }); - } - }, { - key: '_formHandler', - value: function _formHandler() { - var $form = this.$element.closest('form'); - if ($form.data('bootstrap-switch')) { - return; - } - $form.on('reset.bootstrapSwitch', function () { - window.setTimeout(function () { - $form.find('input').filter(function () { - return $(this).data('bootstrap-switch'); - }).each(function () { - return $(this).bootstrapSwitch('state', this.checked); - }); - }, 1); - }).data('bootstrap-switch', true); - } - }, { - key: '_getClass', - value: function _getClass(name) { - return this.options.baseClass + '-' + name; - } - }, { - key: '_getClasses', - value: function _getClasses(classes) { - if (!$.isArray(classes)) { - return [this._getClass(classes)]; - } - return classes.map(this._getClass.bind(this)); - } - }]); - - return BootstrapSwitch; - }(); - - $.fn.bootstrapSwitch = function (option) { - for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; - } - - function reducer(ret, next) { - var $this = $(next); - var existingData = $this.data('bootstrap-switch'); - var data = existingData || new BootstrapSwitch(next, option); - if (!existingData) { - $this.data('bootstrap-switch', data); - } - if (typeof option === 'string') { - return data[option].apply(data, args); - } - return ret; - } - return Array.prototype.reduce.call(this, reducer, this); - }; - $.fn.bootstrapSwitch.Constructor = BootstrapSwitch; - $.fn.bootstrapSwitch.defaults = { - state: true, - size: null, - animate: true, - disabled: false, - readonly: false, - indeterminate: false, - inverse: false, - radioAllOff: false, - onColor: 'primary', - offColor: 'default', - onText: 'ON', - offText: 'OFF', - labelText: ' ', - handleWidth: 'auto', - labelWidth: 'auto', - baseClass: 'bootstrap-switch', - wrapperClass: 'wrapper', - onInit: function onInit() {}, - onSwitchChange: function onSwitchChange() {} - }; -}); diff --git a/hal-core/resources/web/js/lib/bootstrap-switch.min.js b/hal-core/resources/web/js/lib/bootstrap-switch.min.js deleted file mode 100644 index 1381dc11..00000000 --- a/hal-core/resources/web/js/lib/bootstrap-switch.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches. - * - * @version v3.3.4 - * @homepage https://bttstrp.github.io/bootstrap-switch - * @author Mattia Larentis (http://larentis.eu) - * @license Apache-2.0 - */ - -(function(a,b){if('function'==typeof define&&define.amd)define(['jquery'],b);else if('undefined'!=typeof exports)b(require('jquery'));else{b(a.jquery),a.bootstrapSwitch={exports:{}}.exports}})(this,function(a){'use strict';function c(j,k){if(!(j instanceof k))throw new TypeError('Cannot call a class as a function')}var d=function(j){return j&&j.__esModule?j:{default:j}}(a),e=Object.assign||function(j){for(var l,k=1;k',{class:function(){var o=[];return o.push(l.options.state?'on':'off'),l.options.size&&o.push(l.options.size),l.options.disabled&&o.push('disabled'),l.options.readonly&&o.push('readonly'),l.options.indeterminate&&o.push('indeterminate'),l.options.inverse&&o.push('inverse'),l.$element.attr('id')&&o.push('id-'+l.$element.attr('id')),o.map(l._getClass.bind(l)).concat([l.options.baseClass],l._getClasses(l.options.wrapperClass)).join(' ')}}),this.$container=g('
',{class:this._getClass('container')}),this.$on=g('',{html:this.options.onText,class:this._getClass('handle-on')+' '+this._getClass(this.options.onColor)}),this.$off=g('',{html:this.options.offText,class:this._getClass('handle-off')+' '+this._getClass(this.options.offColor)}),this.$label=g('',{html:this.options.labelText,class:this._getClass('label')}),this.$element.on('init.bootstrapSwitch',this.options.onInit.bind(this,k)),this.$element.on('switchChange.bootstrapSwitch',function(){for(var n=arguments.length,o=Array(n),p=0;p-(l._handleWidth/2);l._dragEnd=!1,l.state(l.options.inverse?!p:p)}else l.state(!l.options.state);l._dragStart=!1}},'mouseleave.bootstrapSwitch':function(){l.$label.trigger('mouseup.bootstrapSwitch')}})}},{key:'_externalLabelHandler',value:function(){var l=this,m=this.$element.closest('label');m.on('click',function(n){n.preventDefault(),n.stopImmediatePropagation(),n.target===m[0]&&l.toggleState()})}},{key:'_formHandler',value:function(){var l=this.$element.closest('form');l.data('bootstrap-switch')||l.on('reset.bootstrapSwitch',function(){window.setTimeout(function(){l.find('input').filter(function(){return g(this).data('bootstrap-switch')}).each(function(){return g(this).bootstrapSwitch('state',this.checked)})},1)}).data('bootstrap-switch',!0)}},{key:'_getClass',value:function(l){return this.options.baseClass+'-'+l}},{key:'_getClasses',value:function(l){return g.isArray(l)?l.map(this._getClass.bind(this)):[this._getClass(l)]}}]),j}();g.fn.bootstrapSwitch=function(j){for(var l=arguments.length,m=Array(1 3)) { - throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') - } -}(jQuery); - -/* ======================================================================== - * Bootstrap: transition.js v3.3.7 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - WebkitTransition : 'webkitTransitionEnd', - MozTransition : 'transitionend', - OTransition : 'oTransitionEnd otransitionend', - transition : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - - return false // explicit for ie8 ( ._.) - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false - var $el = this - $(this).one('bsTransitionEnd', function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - - if (!$.support.transition) return - - $.event.special.bsTransitionEnd = { - bindType: $.support.transition.end, - delegateType: $.support.transition.end, - handle: function (e) { - if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) - } - } - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: alert.js v3.3.7 - * http://getbootstrap.com/javascript/#alerts - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.VERSION = '3.3.7' - - Alert.TRANSITION_DURATION = 150 - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector === '#' ? [] : selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.closest('.alert') - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - // detach from parent, fire event then clean up data - $parent.detach().trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one('bsTransitionEnd', removeElement) - .emulateTransitionEnd(Alert.TRANSITION_DURATION) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.alert - - $.fn.alert = Plugin - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: button.js v3.3.7 - * http://getbootstrap.com/javascript/#buttons - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - this.isLoading = false - } - - Button.VERSION = '3.3.7' - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state += 'Text' - - if (data.resetText == null) $el.data('resetText', $el[val]()) - - // push to event loop to allow forms to submit - setTimeout($.proxy(function () { - $el[val](data[state] == null ? this.options[state] : data[state]) - - if (state == 'loadingText') { - this.isLoading = true - $el.addClass(d).attr(d, d).prop(d, true) - } else if (this.isLoading) { - this.isLoading = false - $el.removeClass(d).removeAttr(d).prop(d, false) - } - }, this), 0) - } - - Button.prototype.toggle = function () { - var changed = true - var $parent = this.$element.closest('[data-toggle="buttons"]') - - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') == 'radio') { - if ($input.prop('checked')) changed = false - $parent.find('.active').removeClass('active') - this.$element.addClass('active') - } else if ($input.prop('type') == 'checkbox') { - if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false - this.$element.toggleClass('active') - } - $input.prop('checked', this.$element.hasClass('active')) - if (changed) $input.trigger('change') - } else { - this.$element.attr('aria-pressed', !this.$element.hasClass('active')) - this.$element.toggleClass('active') - } - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - var old = $.fn.button - - $.fn.button = Plugin - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document) - .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { - var $btn = $(e.target).closest('.btn') - Plugin.call($btn, 'toggle') - if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { - // Prevent double click on radios, and the double selections (so cancellation) on checkboxes - e.preventDefault() - // The target component still receive the focus - if ($btn.is('input,button')) $btn.trigger('focus') - else $btn.find('input:visible,button:visible').first().trigger('focus') - } - }) - .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { - $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: carousel.js v3.3.7 - * http://getbootstrap.com/javascript/#carousel - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = null - this.sliding = null - this.interval = null - this.$active = null - this.$items = null - - this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) - - this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element - .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) - .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) - } - - Carousel.VERSION = '3.3.7' - - Carousel.TRANSITION_DURATION = 600 - - Carousel.DEFAULTS = { - interval: 5000, - pause: 'hover', - wrap: true, - keyboard: true - } - - Carousel.prototype.keydown = function (e) { - if (/input|textarea/i.test(e.target.tagName)) return - switch (e.which) { - case 37: this.prev(); break - case 39: this.next(); break - default: return - } - - e.preventDefault() - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getItemIndex = function (item) { - this.$items = item.parent().children('.item') - return this.$items.index(item || this.$active) - } - - Carousel.prototype.getItemForDirection = function (direction, active) { - var activeIndex = this.getItemIndex(active) - var willWrap = (direction == 'prev' && activeIndex === 0) - || (direction == 'next' && activeIndex == (this.$items.length - 1)) - if (willWrap && !this.options.wrap) return active - var delta = direction == 'prev' ? -1 : 1 - var itemIndex = (activeIndex + delta) % this.$items.length - return this.$items.eq(itemIndex) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || this.getItemForDirection(type, $active) - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var that = this - - if ($next.hasClass('active')) return (this.sliding = false) - - var relatedTarget = $next[0] - var slideEvent = $.Event('slide.bs.carousel', { - relatedTarget: relatedTarget, - direction: direction - }) - this.$element.trigger(slideEvent) - if (slideEvent.isDefaultPrevented()) return - - this.sliding = true - - isCycling && this.pause() - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) - $nextIndicator && $nextIndicator.addClass('active') - } - - var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" - if ($.support.transition && this.$element.hasClass('slide')) { - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one('bsTransitionEnd', function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { - that.$element.trigger(slidEvent) - }, 0) - }) - .emulateTransitionEnd(Carousel.TRANSITION_DURATION) - } else { - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger(slidEvent) - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - var old = $.fn.carousel - - $.fn.carousel = Plugin - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - var clickHandler = function (e) { - var href - var $this = $(this) - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 - if (!$target.hasClass('carousel')) return - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - Plugin.call($target, options) - - if (slideIndex) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - } - - $(document) - .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) - .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - Plugin.call($carousel, $carousel.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: collapse.js v3.3.7 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - -/* jshint latedef: false */ - -+function ($) { - 'use strict'; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + - '[data-toggle="collapse"][data-target="#' + element.id + '"]') - this.transitioning = null - - if (this.options.parent) { - this.$parent = this.getParent() - } else { - this.addAriaAndCollapsedClass(this.$element, this.$trigger) - } - - if (this.options.toggle) this.toggle() - } - - Collapse.VERSION = '3.3.7' - - Collapse.TRANSITION_DURATION = 350 - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var activesData - var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') - - if (actives && actives.length) { - activesData = actives.data('bs.collapse') - if (activesData && activesData.transitioning) return - } - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - if (actives && actives.length) { - Plugin.call(actives, 'hide') - activesData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing')[dimension](0) - .attr('aria-expanded', true) - - this.$trigger - .removeClass('collapsed') - .attr('aria-expanded', true) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in')[dimension]('') - this.transitioning = 0 - this.$element - .trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element[dimension](this.$element[dimension]())[0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse in') - .attr('aria-expanded', false) - - this.$trigger - .addClass('collapsed') - .attr('aria-expanded', false) - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .removeClass('collapsing') - .addClass('collapse') - .trigger('hidden.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - Collapse.prototype.getParent = function () { - return $(this.options.parent) - .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') - .each($.proxy(function (i, element) { - var $element = $(element) - this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) - }, this)) - .end() - } - - Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { - var isOpen = $element.hasClass('in') - - $element.attr('aria-expanded', isOpen) - $trigger - .toggleClass('collapsed', !isOpen) - .attr('aria-expanded', isOpen) - } - - function getTargetFromTrigger($trigger) { - var href - var target = $trigger.attr('data-target') - || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - - return $(target) - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.collapse - - $.fn.collapse = Plugin - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var $this = $(this) - - if (!$this.attr('data-target')) e.preventDefault() - - var $target = getTargetFromTrigger($this) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - - Plugin.call($target, option) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: dropdown.js v3.3.7 - * http://getbootstrap.com/javascript/#dropdowns - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle="dropdown"]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.VERSION = '3.3.7' - - function getParent($this) { - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = selector && $(selector) - - return $parent && $parent.length ? $parent : $this.parent() - } - - function clearMenus(e) { - if (e && e.which === 3) return - $(backdrop).remove() - $(toggle).each(function () { - var $this = $(this) - var $parent = getParent($this) - var relatedTarget = { relatedTarget: this } - - if (!$parent.hasClass('open')) return - - if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return - - $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) - - if (e.isDefaultPrevented()) return - - $this.attr('aria-expanded', 'false') - $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) - }) - } - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $(document.createElement('div')) - .addClass('dropdown-backdrop') - .insertAfter($(this)) - .on('click', clearMenus) - } - - var relatedTarget = { relatedTarget: this } - $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) - - if (e.isDefaultPrevented()) return - - $this - .trigger('focus') - .attr('aria-expanded', 'true') - - $parent - .toggleClass('open') - .trigger($.Event('shown.bs.dropdown', relatedTarget)) - } - - return false - } - - Dropdown.prototype.keydown = function (e) { - if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return - - var $this = $(this) - - e.preventDefault() - e.stopPropagation() - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - if (!isActive && e.which != 27 || isActive && e.which == 27) { - if (e.which == 27) $parent.find(toggle).trigger('focus') - return $this.trigger('click') - } - - var desc = ' li:not(.disabled):visible a' - var $items = $parent.find('.dropdown-menu' + desc) - - if (!$items.length) return - - var index = $items.index(e.target) - - if (e.which == 38 && index > 0) index-- // up - if (e.which == 40 && index < $items.length - 1) index++ // down - if (!~index) index = 0 - - $items.eq(index).trigger('focus') - } - - - // DROPDOWN PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.dropdown') - - if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.dropdown - - $.fn.dropdown = Plugin - $.fn.dropdown.Constructor = Dropdown - - - // DROPDOWN NO CONFLICT - // ==================== - - $.fn.dropdown.noConflict = function () { - $.fn.dropdown = old - return this - } - - - // APPLY TO STANDARD DROPDOWN ELEMENTS - // =================================== - - $(document) - .on('click.bs.dropdown.data-api', clearMenus) - .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) - .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) - .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: modal.js v3.3.7 - * http://getbootstrap.com/javascript/#modals - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // MODAL CLASS DEFINITION - // ====================== - - var Modal = function (element, options) { - this.options = options - this.$body = $(document.body) - this.$element = $(element) - this.$dialog = this.$element.find('.modal-dialog') - this.$backdrop = null - this.isShown = null - this.originalBodyPad = null - this.scrollbarWidth = 0 - this.ignoreBackdropClick = false - - if (this.options.remote) { - this.$element - .find('.modal-content') - .load(this.options.remote, $.proxy(function () { - this.$element.trigger('loaded.bs.modal') - }, this)) - } - } - - Modal.VERSION = '3.3.7' - - Modal.TRANSITION_DURATION = 300 - Modal.BACKDROP_TRANSITION_DURATION = 150 - - Modal.DEFAULTS = { - backdrop: true, - keyboard: true, - show: true - } - - Modal.prototype.toggle = function (_relatedTarget) { - return this.isShown ? this.hide() : this.show(_relatedTarget) - } - - Modal.prototype.show = function (_relatedTarget) { - var that = this - var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) - - this.$element.trigger(e) - - if (this.isShown || e.isDefaultPrevented()) return - - this.isShown = true - - this.checkScrollbar() - this.setScrollbar() - this.$body.addClass('modal-open') - - this.escape() - this.resize() - - this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) - - this.$dialog.on('mousedown.dismiss.bs.modal', function () { - that.$element.one('mouseup.dismiss.bs.modal', function (e) { - if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true - }) - }) - - this.backdrop(function () { - var transition = $.support.transition && that.$element.hasClass('fade') - - if (!that.$element.parent().length) { - that.$element.appendTo(that.$body) // don't move modals dom position - } - - that.$element - .show() - .scrollTop(0) - - that.adjustDialog() - - if (transition) { - that.$element[0].offsetWidth // force reflow - } - - that.$element.addClass('in') - - that.enforceFocus() - - var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) - - transition ? - that.$dialog // wait for modal to slide in - .one('bsTransitionEnd', function () { - that.$element.trigger('focus').trigger(e) - }) - .emulateTransitionEnd(Modal.TRANSITION_DURATION) : - that.$element.trigger('focus').trigger(e) - }) - } - - Modal.prototype.hide = function (e) { - if (e) e.preventDefault() - - e = $.Event('hide.bs.modal') - - this.$element.trigger(e) - - if (!this.isShown || e.isDefaultPrevented()) return - - this.isShown = false - - this.escape() - this.resize() - - $(document).off('focusin.bs.modal') - - this.$element - .removeClass('in') - .off('click.dismiss.bs.modal') - .off('mouseup.dismiss.bs.modal') - - this.$dialog.off('mousedown.dismiss.bs.modal') - - $.support.transition && this.$element.hasClass('fade') ? - this.$element - .one('bsTransitionEnd', $.proxy(this.hideModal, this)) - .emulateTransitionEnd(Modal.TRANSITION_DURATION) : - this.hideModal() - } - - Modal.prototype.enforceFocus = function () { - $(document) - .off('focusin.bs.modal') // guard against infinite focus loop - .on('focusin.bs.modal', $.proxy(function (e) { - if (document !== e.target && - this.$element[0] !== e.target && - !this.$element.has(e.target).length) { - this.$element.trigger('focus') - } - }, this)) - } - - Modal.prototype.escape = function () { - if (this.isShown && this.options.keyboard) { - this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { - e.which == 27 && this.hide() - }, this)) - } else if (!this.isShown) { - this.$element.off('keydown.dismiss.bs.modal') - } - } - - Modal.prototype.resize = function () { - if (this.isShown) { - $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) - } else { - $(window).off('resize.bs.modal') - } - } - - Modal.prototype.hideModal = function () { - var that = this - this.$element.hide() - this.backdrop(function () { - that.$body.removeClass('modal-open') - that.resetAdjustments() - that.resetScrollbar() - that.$element.trigger('hidden.bs.modal') - }) - } - - Modal.prototype.removeBackdrop = function () { - this.$backdrop && this.$backdrop.remove() - this.$backdrop = null - } - - Modal.prototype.backdrop = function (callback) { - var that = this - var animate = this.$element.hasClass('fade') ? 'fade' : '' - - if (this.isShown && this.options.backdrop) { - var doAnimate = $.support.transition && animate - - this.$backdrop = $(document.createElement('div')) - .addClass('modal-backdrop ' + animate) - .appendTo(this.$body) - - this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { - if (this.ignoreBackdropClick) { - this.ignoreBackdropClick = false - return - } - if (e.target !== e.currentTarget) return - this.options.backdrop == 'static' - ? this.$element[0].focus() - : this.hide() - }, this)) - - if (doAnimate) this.$backdrop[0].offsetWidth // force reflow - - this.$backdrop.addClass('in') - - if (!callback) return - - doAnimate ? - this.$backdrop - .one('bsTransitionEnd', callback) - .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : - callback() - - } else if (!this.isShown && this.$backdrop) { - this.$backdrop.removeClass('in') - - var callbackRemove = function () { - that.removeBackdrop() - callback && callback() - } - $.support.transition && this.$element.hasClass('fade') ? - this.$backdrop - .one('bsTransitionEnd', callbackRemove) - .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : - callbackRemove() - - } else if (callback) { - callback() - } - } - - // these following methods are used to handle overflowing modals - - Modal.prototype.handleUpdate = function () { - this.adjustDialog() - } - - Modal.prototype.adjustDialog = function () { - var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight - - this.$element.css({ - paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', - paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' - }) - } - - Modal.prototype.resetAdjustments = function () { - this.$element.css({ - paddingLeft: '', - paddingRight: '' - }) - } - - Modal.prototype.checkScrollbar = function () { - var fullWindowWidth = window.innerWidth - if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 - var documentElementRect = document.documentElement.getBoundingClientRect() - fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) - } - this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth - this.scrollbarWidth = this.measureScrollbar() - } - - Modal.prototype.setScrollbar = function () { - var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) - this.originalBodyPad = document.body.style.paddingRight || '' - if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) - } - - Modal.prototype.resetScrollbar = function () { - this.$body.css('padding-right', this.originalBodyPad) - } - - Modal.prototype.measureScrollbar = function () { // thx walsh - var scrollDiv = document.createElement('div') - scrollDiv.className = 'modal-scrollbar-measure' - this.$body.append(scrollDiv) - var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth - this.$body[0].removeChild(scrollDiv) - return scrollbarWidth - } - - - // MODAL PLUGIN DEFINITION - // ======================= - - function Plugin(option, _relatedTarget) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.modal') - var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data) $this.data('bs.modal', (data = new Modal(this, options))) - if (typeof option == 'string') data[option](_relatedTarget) - else if (options.show) data.show(_relatedTarget) - }) - } - - var old = $.fn.modal - - $.fn.modal = Plugin - $.fn.modal.Constructor = Modal - - - // MODAL NO CONFLICT - // ================= - - $.fn.modal.noConflict = function () { - $.fn.modal = old - return this - } - - - // MODAL DATA-API - // ============== - - $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { - var $this = $(this) - var href = $this.attr('href') - var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 - var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) - - if ($this.is('a')) e.preventDefault() - - $target.one('show.bs.modal', function (showEvent) { - if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown - $target.one('hidden.bs.modal', function () { - $this.is(':visible') && $this.trigger('focus') - }) - }) - Plugin.call($target, option, this) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: tooltip.js v3.3.7 - * http://getbootstrap.com/javascript/#tooltip - * Inspired by the original jQuery.tipsy by Jason Frame - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TOOLTIP PUBLIC CLASS DEFINITION - // =============================== - - var Tooltip = function (element, options) { - this.type = null - this.options = null - this.enabled = null - this.timeout = null - this.hoverState = null - this.$element = null - this.inState = null - - this.init('tooltip', element, options) - } - - Tooltip.VERSION = '3.3.7' - - Tooltip.TRANSITION_DURATION = 150 - - Tooltip.DEFAULTS = { - animation: true, - placement: 'top', - selector: false, - template: '', - trigger: 'hover focus', - title: '', - delay: 0, - html: false, - container: false, - viewport: { - selector: 'body', - padding: 0 - } - } - - Tooltip.prototype.init = function (type, element, options) { - this.enabled = true - this.type = type - this.$element = $(element) - this.options = this.getOptions(options) - this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) - this.inState = { click: false, hover: false, focus: false } - - if (this.$element[0] instanceof document.constructor && !this.options.selector) { - throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') - } - - var triggers = this.options.trigger.split(' ') - - for (var i = triggers.length; i--;) { - var trigger = triggers[i] - - if (trigger == 'click') { - this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) - } else if (trigger != 'manual') { - var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' - var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' - - this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) - } - } - - this.options.selector ? - (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : - this.fixTitle() - } - - Tooltip.prototype.getDefaults = function () { - return Tooltip.DEFAULTS - } - - Tooltip.prototype.getOptions = function (options) { - options = $.extend({}, this.getDefaults(), this.$element.data(), options) - - if (options.delay && typeof options.delay == 'number') { - options.delay = { - show: options.delay, - hide: options.delay - } - } - - return options - } - - Tooltip.prototype.getDelegateOptions = function () { - var options = {} - var defaults = this.getDefaults() - - this._options && $.each(this._options, function (key, value) { - if (defaults[key] != value) options[key] = value - }) - - return options - } - - Tooltip.prototype.enter = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true - } - - if (self.tip().hasClass('in') || self.hoverState == 'in') { - self.hoverState = 'in' - return - } - - clearTimeout(self.timeout) - - self.hoverState = 'in' - - if (!self.options.delay || !self.options.delay.show) return self.show() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'in') self.show() - }, self.options.delay.show) - } - - Tooltip.prototype.isInStateTrue = function () { - for (var key in this.inState) { - if (this.inState[key]) return true - } - - return false - } - - Tooltip.prototype.leave = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false - } - - if (self.isInStateTrue()) return - - clearTimeout(self.timeout) - - self.hoverState = 'out' - - if (!self.options.delay || !self.options.delay.hide) return self.hide() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'out') self.hide() - }, self.options.delay.hide) - } - - Tooltip.prototype.show = function () { - var e = $.Event('show.bs.' + this.type) - - if (this.hasContent() && this.enabled) { - this.$element.trigger(e) - - var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) - if (e.isDefaultPrevented() || !inDom) return - var that = this - - var $tip = this.tip() - - var tipId = this.getUID(this.type) - - this.setContent() - $tip.attr('id', tipId) - this.$element.attr('aria-describedby', tipId) - - if (this.options.animation) $tip.addClass('fade') - - var placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, $tip[0], this.$element[0]) : - this.options.placement - - var autoToken = /\s?auto?\s?/i - var autoPlace = autoToken.test(placement) - if (autoPlace) placement = placement.replace(autoToken, '') || 'top' - - $tip - .detach() - .css({ top: 0, left: 0, display: 'block' }) - .addClass(placement) - .data('bs.' + this.type, this) - - this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) - this.$element.trigger('inserted.bs.' + this.type) - - var pos = this.getPosition() - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (autoPlace) { - var orgPlacement = placement - var viewportDim = this.getPosition(this.$viewport) - - placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : - placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : - placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : - placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : - placement - - $tip - .removeClass(orgPlacement) - .addClass(placement) - } - - var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) - - this.applyPlacement(calculatedOffset, placement) - - var complete = function () { - var prevHoverState = that.hoverState - that.$element.trigger('shown.bs.' + that.type) - that.hoverState = null - - if (prevHoverState == 'out') that.leave(that) - } - - $.support.transition && this.$tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - } - } - - Tooltip.prototype.applyPlacement = function (offset, placement) { - var $tip = this.tip() - var width = $tip[0].offsetWidth - var height = $tip[0].offsetHeight - - // manually read margins because getBoundingClientRect includes difference - var marginTop = parseInt($tip.css('margin-top'), 10) - var marginLeft = parseInt($tip.css('margin-left'), 10) - - // we must check for NaN for ie 8/9 - if (isNaN(marginTop)) marginTop = 0 - if (isNaN(marginLeft)) marginLeft = 0 - - offset.top += marginTop - offset.left += marginLeft - - // $.fn.offset doesn't round pixel values - // so we use setOffset directly with our own function B-0 - $.offset.setOffset($tip[0], $.extend({ - using: function (props) { - $tip.css({ - top: Math.round(props.top), - left: Math.round(props.left) - }) - } - }, offset), 0) - - $tip.addClass('in') - - // check to see if placing tip in new offset caused the tip to resize itself - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (placement == 'top' && actualHeight != height) { - offset.top = offset.top + height - actualHeight - } - - var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) - - if (delta.left) offset.left += delta.left - else offset.top += delta.top - - var isVertical = /top|bottom/.test(placement) - var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight - var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' - - $tip.offset(offset) - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) - } - - Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { - this.arrow() - .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') - .css(isVertical ? 'top' : 'left', '') - } - - Tooltip.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - - $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) - $tip.removeClass('fade in top bottom left right') - } - - Tooltip.prototype.hide = function (callback) { - var that = this - var $tip = $(this.$tip) - var e = $.Event('hide.bs.' + this.type) - - function complete() { - if (that.hoverState != 'in') $tip.detach() - if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. - that.$element - .removeAttr('aria-describedby') - .trigger('hidden.bs.' + that.type) - } - callback && callback() - } - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - $tip.removeClass('in') - - $.support.transition && $tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - - this.hoverState = null - - return this - } - - Tooltip.prototype.fixTitle = function () { - var $e = this.$element - if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { - $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') - } - } - - Tooltip.prototype.hasContent = function () { - return this.getTitle() - } - - Tooltip.prototype.getPosition = function ($element) { - $element = $element || this.$element - - var el = $element[0] - var isBody = el.tagName == 'BODY' - - var elRect = el.getBoundingClientRect() - if (elRect.width == null) { - // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 - elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) - } - var isSvg = window.SVGElement && el instanceof window.SVGElement - // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. - // See https://github.com/twbs/bootstrap/issues/20280 - var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) - var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } - var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null - - return $.extend({}, elRect, scroll, outerDims, elOffset) - } - - Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } - - } - - Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { - var delta = { top: 0, left: 0 } - if (!this.$viewport) return delta - - var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 - var viewportDimensions = this.getPosition(this.$viewport) - - if (/right|left/.test(placement)) { - var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll - var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight - if (topEdgeOffset < viewportDimensions.top) { // top overflow - delta.top = viewportDimensions.top - topEdgeOffset - } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow - delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset - } - } else { - var leftEdgeOffset = pos.left - viewportPadding - var rightEdgeOffset = pos.left + viewportPadding + actualWidth - if (leftEdgeOffset < viewportDimensions.left) { // left overflow - delta.left = viewportDimensions.left - leftEdgeOffset - } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow - delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset - } - } - - return delta - } - - Tooltip.prototype.getTitle = function () { - var title - var $e = this.$element - var o = this.options - - title = $e.attr('data-original-title') - || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) - - return title - } - - Tooltip.prototype.getUID = function (prefix) { - do prefix += ~~(Math.random() * 1000000) - while (document.getElementById(prefix)) - return prefix - } - - Tooltip.prototype.tip = function () { - if (!this.$tip) { - this.$tip = $(this.options.template) - if (this.$tip.length != 1) { - throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') - } - } - return this.$tip - } - - Tooltip.prototype.arrow = function () { - return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) - } - - Tooltip.prototype.enable = function () { - this.enabled = true - } - - Tooltip.prototype.disable = function () { - this.enabled = false - } - - Tooltip.prototype.toggleEnabled = function () { - this.enabled = !this.enabled - } - - Tooltip.prototype.toggle = function (e) { - var self = this - if (e) { - self = $(e.currentTarget).data('bs.' + this.type) - if (!self) { - self = new this.constructor(e.currentTarget, this.getDelegateOptions()) - $(e.currentTarget).data('bs.' + this.type, self) - } - } - - if (e) { - self.inState.click = !self.inState.click - if (self.isInStateTrue()) self.enter(self) - else self.leave(self) - } else { - self.tip().hasClass('in') ? self.leave(self) : self.enter(self) - } - } - - Tooltip.prototype.destroy = function () { - var that = this - clearTimeout(this.timeout) - this.hide(function () { - that.$element.off('.' + that.type).removeData('bs.' + that.type) - if (that.$tip) { - that.$tip.detach() - } - that.$tip = null - that.$arrow = null - that.$viewport = null - that.$element = null - }) - } - - - // TOOLTIP PLUGIN DEFINITION - // ========================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tooltip') - var options = typeof option == 'object' && option - - if (!data && /destroy|hide/.test(option)) return - if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.tooltip - - $.fn.tooltip = Plugin - $.fn.tooltip.Constructor = Tooltip - - - // TOOLTIP NO CONFLICT - // =================== - - $.fn.tooltip.noConflict = function () { - $.fn.tooltip = old - return this - } - -}(jQuery); - -/* ======================================================================== - * Bootstrap: popover.js v3.3.7 - * http://getbootstrap.com/javascript/#popovers - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // POPOVER PUBLIC CLASS DEFINITION - // =============================== - - var Popover = function (element, options) { - this.init('popover', element, options) - } - - if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') - - Popover.VERSION = '3.3.7' - - Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { - placement: 'right', - trigger: 'click', - content: '', - template: '' - }) - - - // NOTE: POPOVER EXTENDS tooltip.js - // ================================ - - Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) - - Popover.prototype.constructor = Popover - - Popover.prototype.getDefaults = function () { - return Popover.DEFAULTS - } - - Popover.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - var content = this.getContent() - - $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) - $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events - this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' - ](content) - - $tip.removeClass('fade top bottom left right in') - - // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do - // this manually by checking the contents. - if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() - } - - Popover.prototype.hasContent = function () { - return this.getTitle() || this.getContent() - } - - Popover.prototype.getContent = function () { - var $e = this.$element - var o = this.options - - return $e.attr('data-content') - || (typeof o.content == 'function' ? - o.content.call($e[0]) : - o.content) - } - - Popover.prototype.arrow = function () { - return (this.$arrow = this.$arrow || this.tip().find('.arrow')) - } - - - // POPOVER PLUGIN DEFINITION - // ========================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.popover') - var options = typeof option == 'object' && option - - if (!data && /destroy|hide/.test(option)) return - if (!data) $this.data('bs.popover', (data = new Popover(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.popover - - $.fn.popover = Plugin - $.fn.popover.Constructor = Popover - - - // POPOVER NO CONFLICT - // =================== - - $.fn.popover.noConflict = function () { - $.fn.popover = old - return this - } - -}(jQuery); - -/* ======================================================================== - * Bootstrap: scrollspy.js v3.3.7 - * http://getbootstrap.com/javascript/#scrollspy - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // SCROLLSPY CLASS DEFINITION - // ========================== - - function ScrollSpy(element, options) { - this.$body = $(document.body) - this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) - this.options = $.extend({}, ScrollSpy.DEFAULTS, options) - this.selector = (this.options.target || '') + ' .nav li > a' - this.offsets = [] - this.targets = [] - this.activeTarget = null - this.scrollHeight = 0 - - this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) - this.refresh() - this.process() - } - - ScrollSpy.VERSION = '3.3.7' - - ScrollSpy.DEFAULTS = { - offset: 10 - } - - ScrollSpy.prototype.getScrollHeight = function () { - return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) - } - - ScrollSpy.prototype.refresh = function () { - var that = this - var offsetMethod = 'offset' - var offsetBase = 0 - - this.offsets = [] - this.targets = [] - this.scrollHeight = this.getScrollHeight() - - if (!$.isWindow(this.$scrollElement[0])) { - offsetMethod = 'position' - offsetBase = this.$scrollElement.scrollTop() - } - - this.$body - .find(this.selector) - .map(function () { - var $el = $(this) - var href = $el.data('target') || $el.attr('href') - var $href = /^#./.test(href) && $(href) - - return ($href - && $href.length - && $href.is(':visible') - && [[$href[offsetMethod]().top + offsetBase, href]]) || null - }) - .sort(function (a, b) { return a[0] - b[0] }) - .each(function () { - that.offsets.push(this[0]) - that.targets.push(this[1]) - }) - } - - ScrollSpy.prototype.process = function () { - var scrollTop = this.$scrollElement.scrollTop() + this.options.offset - var scrollHeight = this.getScrollHeight() - var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() - var offsets = this.offsets - var targets = this.targets - var activeTarget = this.activeTarget - var i - - if (this.scrollHeight != scrollHeight) { - this.refresh() - } - - if (scrollTop >= maxScroll) { - return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) - } - - if (activeTarget && scrollTop < offsets[0]) { - this.activeTarget = null - return this.clear() - } - - for (i = offsets.length; i--;) { - activeTarget != targets[i] - && scrollTop >= offsets[i] - && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) - && this.activate(targets[i]) - } - } - - ScrollSpy.prototype.activate = function (target) { - this.activeTarget = target - - this.clear() - - var selector = this.selector + - '[data-target="' + target + '"],' + - this.selector + '[href="' + target + '"]' - - var active = $(selector) - .parents('li') - .addClass('active') - - if (active.parent('.dropdown-menu').length) { - active = active - .closest('li.dropdown') - .addClass('active') - } - - active.trigger('activate.bs.scrollspy') - } - - ScrollSpy.prototype.clear = function () { - $(this.selector) - .parentsUntil(this.options.target, '.active') - .removeClass('active') - } - - - // SCROLLSPY PLUGIN DEFINITION - // =========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.scrollspy') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.scrollspy - - $.fn.scrollspy = Plugin - $.fn.scrollspy.Constructor = ScrollSpy - - - // SCROLLSPY NO CONFLICT - // ===================== - - $.fn.scrollspy.noConflict = function () { - $.fn.scrollspy = old - return this - } - - - // SCROLLSPY DATA-API - // ================== - - $(window).on('load.bs.scrollspy.data-api', function () { - $('[data-spy="scroll"]').each(function () { - var $spy = $(this) - Plugin.call($spy, $spy.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: tab.js v3.3.7 - * http://getbootstrap.com/javascript/#tabs - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TAB CLASS DEFINITION - // ==================== - - var Tab = function (element) { - // jscs:disable requireDollarBeforejQueryAssignment - this.element = $(element) - // jscs:enable requireDollarBeforejQueryAssignment - } - - Tab.VERSION = '3.3.7' - - Tab.TRANSITION_DURATION = 150 - - Tab.prototype.show = function () { - var $this = this.element - var $ul = $this.closest('ul:not(.dropdown-menu)') - var selector = $this.data('target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - if ($this.parent('li').hasClass('active')) return - - var $previous = $ul.find('.active:last a') - var hideEvent = $.Event('hide.bs.tab', { - relatedTarget: $this[0] - }) - var showEvent = $.Event('show.bs.tab', { - relatedTarget: $previous[0] - }) - - $previous.trigger(hideEvent) - $this.trigger(showEvent) - - if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return - - var $target = $(selector) - - this.activate($this.closest('li'), $ul) - this.activate($target, $target.parent(), function () { - $previous.trigger({ - type: 'hidden.bs.tab', - relatedTarget: $this[0] - }) - $this.trigger({ - type: 'shown.bs.tab', - relatedTarget: $previous[0] - }) - }) - } - - Tab.prototype.activate = function (element, container, callback) { - var $active = container.find('> .active') - var transition = callback - && $.support.transition - && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) - - function next() { - $active - .removeClass('active') - .find('> .dropdown-menu > .active') - .removeClass('active') - .end() - .find('[data-toggle="tab"]') - .attr('aria-expanded', false) - - element - .addClass('active') - .find('[data-toggle="tab"]') - .attr('aria-expanded', true) - - if (transition) { - element[0].offsetWidth // reflow for transition - element.addClass('in') - } else { - element.removeClass('fade') - } - - if (element.parent('.dropdown-menu').length) { - element - .closest('li.dropdown') - .addClass('active') - .end() - .find('[data-toggle="tab"]') - .attr('aria-expanded', true) - } - - callback && callback() - } - - $active.length && transition ? - $active - .one('bsTransitionEnd', next) - .emulateTransitionEnd(Tab.TRANSITION_DURATION) : - next() - - $active.removeClass('in') - } - - - // TAB PLUGIN DEFINITION - // ===================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tab') - - if (!data) $this.data('bs.tab', (data = new Tab(this))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.tab - - $.fn.tab = Plugin - $.fn.tab.Constructor = Tab - - - // TAB NO CONFLICT - // =============== - - $.fn.tab.noConflict = function () { - $.fn.tab = old - return this - } - - - // TAB DATA-API - // ============ - - var clickHandler = function (e) { - e.preventDefault() - Plugin.call($(this), 'show') - } - - $(document) - .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) - .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: affix.js v3.3.7 - * http://getbootstrap.com/javascript/#affix - * ======================================================================== - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // AFFIX CLASS DEFINITION - // ====================== - - var Affix = function (element, options) { - this.options = $.extend({}, Affix.DEFAULTS, options) - - this.$target = $(this.options.target) - .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) - .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) - - this.$element = $(element) - this.affixed = null - this.unpin = null - this.pinnedOffset = null - - this.checkPosition() - } - - Affix.VERSION = '3.3.7' - - Affix.RESET = 'affix affix-top affix-bottom' - - Affix.DEFAULTS = { - offset: 0, - target: window - } - - Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() - var targetHeight = this.$target.height() - - if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false - - if (this.affixed == 'bottom') { - if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' - return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' - } - - var initializing = this.affixed == null - var colliderTop = initializing ? scrollTop : position.top - var colliderHeight = initializing ? targetHeight : height - - if (offsetTop != null && scrollTop <= offsetTop) return 'top' - if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' - - return false - } - - Affix.prototype.getPinnedOffset = function () { - if (this.pinnedOffset) return this.pinnedOffset - this.$element.removeClass(Affix.RESET).addClass('affix') - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() - return (this.pinnedOffset = position.top - scrollTop) - } - - Affix.prototype.checkPositionWithEventLoop = function () { - setTimeout($.proxy(this.checkPosition, this), 1) - } - - Affix.prototype.checkPosition = function () { - if (!this.$element.is(':visible')) return - - var height = this.$element.height() - var offset = this.options.offset - var offsetTop = offset.top - var offsetBottom = offset.bottom - var scrollHeight = Math.max($(document).height(), $(document.body).height()) - - if (typeof offset != 'object') offsetBottom = offsetTop = offset - if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) - if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) - - var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) - - if (this.affixed != affix) { - if (this.unpin != null) this.$element.css('top', '') - - var affixType = 'affix' + (affix ? '-' + affix : '') - var e = $.Event(affixType + '.bs.affix') - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - this.affixed = affix - this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null - - this.$element - .removeClass(Affix.RESET) - .addClass(affixType) - .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') - } - - if (affix == 'bottom') { - this.$element.offset({ - top: scrollHeight - height - offsetBottom - }) - } - } - - - // AFFIX PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.affix') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.affix', (data = new Affix(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.affix - - $.fn.affix = Plugin - $.fn.affix.Constructor = Affix - - - // AFFIX NO CONFLICT - // ================= - - $.fn.affix.noConflict = function () { - $.fn.affix = old - return this - } - - - // AFFIX DATA-API - // ============== - - $(window).on('load', function () { - $('[data-spy="affix"]').each(function () { - var $spy = $(this) - var data = $spy.data() - - data.offset = data.offset || {} - - if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom - if (data.offsetTop != null) data.offset.top = data.offsetTop - - Plugin.call($spy, data) - }) - }) - -}(jQuery); diff --git a/hal-core/resources/web/js/lib/bootstrap.min.js b/hal-core/resources/web/js/lib/bootstrap.min.js deleted file mode 100644 index 9bcd2fcc..00000000 --- a/hal-core/resources/web/js/lib/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under the MIT license - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/hal-core/resources/web/js/lib/c3.LICENSE b/hal-core/resources/web/js/lib/c3.LICENSE deleted file mode 100644 index 29ce9cb0..00000000 --- a/hal-core/resources/web/js/lib/c3.LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Masayuki Tanaka - -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. diff --git a/hal-core/resources/web/js/lib/c3.LICENSE.txt b/hal-core/resources/web/js/lib/c3.LICENSE.txt deleted file mode 100644 index 29ce9cb0..00000000 --- a/hal-core/resources/web/js/lib/c3.LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Masayuki Tanaka - -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. diff --git a/hal-core/resources/web/js/lib/c3.js b/hal-core/resources/web/js/lib/c3.js deleted file mode 100644 index 2ce7f7e0..00000000 --- a/hal-core/resources/web/js/lib/c3.js +++ /dev/null @@ -1,8202 +0,0 @@ -(function (window) { - 'use strict'; - - /*global define, module, exports, require */ - - var c3 = { version: "0.4.11" }; - - var c3_chart_fn, - c3_chart_internal_fn, - c3_chart_internal_axis_fn; - - function API(owner) { - this.owner = owner; - } - - function inherit(base, derived) { - - if (Object.create) { - derived.prototype = Object.create(base.prototype); - } else { - var f = function f() {}; - f.prototype = base.prototype; - derived.prototype = new f(); - } - - derived.prototype.constructor = derived; - - return derived; - } - - function Chart(config) { - var $$ = this.internal = new ChartInternal(this); - $$.loadConfig(config); - - $$.beforeInit(config); - $$.init(); - $$.afterInit(config); - - // bind "this" to nested API - (function bindThis(fn, target, argThis) { - Object.keys(fn).forEach(function (key) { - target[key] = fn[key].bind(argThis); - if (Object.keys(fn[key]).length > 0) { - bindThis(fn[key], target[key], argThis); - } - }); - })(c3_chart_fn, this, this); - } - - function ChartInternal(api) { - var $$ = this; - $$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined; - $$.api = api; - $$.config = $$.getDefaultConfig(); - $$.data = {}; - $$.cache = {}; - $$.axes = {}; - } - - c3.generate = function (config) { - return new Chart(config); - }; - - c3.chart = { - fn: Chart.prototype, - internal: { - fn: ChartInternal.prototype, - axis: { - fn: Axis.prototype - } - } - }; - c3_chart_fn = c3.chart.fn; - c3_chart_internal_fn = c3.chart.internal.fn; - c3_chart_internal_axis_fn = c3.chart.internal.axis.fn; - - c3_chart_internal_fn.beforeInit = function () { - // can do something - }; - c3_chart_internal_fn.afterInit = function () { - // can do something - }; - c3_chart_internal_fn.init = function () { - var $$ = this, config = $$.config; - - $$.initParams(); - - if (config.data_url) { - $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData); - } - else if (config.data_json) { - $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys)); - } - else if (config.data_rows) { - $$.initWithData($$.convertRowsToData(config.data_rows)); - } - else if (config.data_columns) { - $$.initWithData($$.convertColumnsToData(config.data_columns)); - } - else { - throw Error('url or json or rows or columns is required.'); - } - }; - - c3_chart_internal_fn.initParams = function () { - var $$ = this, d3 = $$.d3, config = $$.config; - - // MEMO: clipId needs to be unique because it conflicts when multiple charts exist - $$.clipId = "c3-" + (+new Date()) + '-clip', - $$.clipIdForXAxis = $$.clipId + '-xaxis', - $$.clipIdForYAxis = $$.clipId + '-yaxis', - $$.clipIdForGrid = $$.clipId + '-grid', - $$.clipIdForSubchart = $$.clipId + '-subchart', - $$.clipPath = $$.getClipPath($$.clipId), - $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis), - $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis); - $$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid), - $$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart), - - $$.dragStart = null; - $$.dragging = false; - $$.flowing = false; - $$.cancelClick = false; - $$.mouseover = false; - $$.transiting = false; - - $$.color = $$.generateColor(); - $$.levelColor = $$.generateLevelColor(); - - $$.dataTimeFormat = config.data_xLocaltime ? d3.time.format : d3.time.format.utc; - $$.axisTimeFormat = config.axis_x_localtime ? d3.time.format : d3.time.format.utc; - $$.defaultAxisTimeFormat = $$.axisTimeFormat.multi([ - [".%L", function (d) { return d.getMilliseconds(); }], - [":%S", function (d) { return d.getSeconds(); }], - ["%I:%M", function (d) { return d.getMinutes(); }], - ["%I %p", function (d) { return d.getHours(); }], - ["%-m/%-d", function (d) { return d.getDay() && d.getDate() !== 1; }], - ["%-m/%-d", function (d) { return d.getDate() !== 1; }], - ["%-m/%-d", function (d) { return d.getMonth(); }], - ["%Y/%-m/%-d", function () { return true; }] - ]); - - $$.hiddenTargetIds = []; - $$.hiddenLegendIds = []; - $$.focusedTargetIds = []; - $$.defocusedTargetIds = []; - - $$.xOrient = config.axis_rotated ? "left" : "bottom"; - $$.yOrient = config.axis_rotated ? (config.axis_y_inner ? "top" : "bottom") : (config.axis_y_inner ? "right" : "left"); - $$.y2Orient = config.axis_rotated ? (config.axis_y2_inner ? "bottom" : "top") : (config.axis_y2_inner ? "left" : "right"); - $$.subXOrient = config.axis_rotated ? "left" : "bottom"; - - $$.isLegendRight = config.legend_position === 'right'; - $$.isLegendInset = config.legend_position === 'inset'; - $$.isLegendTop = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'top-right'; - $$.isLegendLeft = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'bottom-left'; - $$.legendStep = 0; - $$.legendItemWidth = 0; - $$.legendItemHeight = 0; - - $$.currentMaxTickWidths = { - x: 0, - y: 0, - y2: 0 - }; - - $$.rotated_padding_left = 30; - $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30; - $$.rotated_padding_top = 5; - - $$.withoutFadeIn = {}; - - $$.intervalForObserveInserted = undefined; - - $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js - }; - - c3_chart_internal_fn.initChartElements = function () { - if (this.initBar) { this.initBar(); } - if (this.initLine) { this.initLine(); } - if (this.initArc) { this.initArc(); } - if (this.initGauge) { this.initGauge(); } - if (this.initText) { this.initText(); } - }; - - c3_chart_internal_fn.initWithData = function (data) { - var $$ = this, d3 = $$.d3, config = $$.config; - var defs, main, binding = true; - - $$.axis = new Axis($$); - - if ($$.initPie) { $$.initPie(); } - if ($$.initBrush) { $$.initBrush(); } - if ($$.initZoom) { $$.initZoom(); } - - if (!config.bindto) { - $$.selectChart = d3.selectAll([]); - } - else if (typeof config.bindto.node === 'function') { - $$.selectChart = config.bindto; - } - else { - $$.selectChart = d3.select(config.bindto); - } - if ($$.selectChart.empty()) { - $$.selectChart = d3.select(document.createElement('div')).style('opacity', 0); - $$.observeInserted($$.selectChart); - binding = false; - } - $$.selectChart.html("").classed("c3", true); - - // Init data as targets - $$.data.xs = {}; - $$.data.targets = $$.convertDataToTargets(data); - - if (config.data_filter) { - $$.data.targets = $$.data.targets.filter(config.data_filter); - } - - // Set targets to hide if needed - if (config.data_hide) { - $$.addHiddenTargetIds(config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide); - } - if (config.legend_hide) { - $$.addHiddenLegendIds(config.legend_hide === true ? $$.mapToIds($$.data.targets) : config.legend_hide); - } - - // when gauge, hide legend // TODO: fix - if ($$.hasType('gauge')) { - config.legend_show = false; - } - - // Init sizes and scales - $$.updateSizes(); - $$.updateScales(); - - // Set domains for each scale - $$.x.domain(d3.extent($$.getXDomain($$.data.targets))); - $$.y.domain($$.getYDomain($$.data.targets, 'y')); - $$.y2.domain($$.getYDomain($$.data.targets, 'y2')); - $$.subX.domain($$.x.domain()); - $$.subY.domain($$.y.domain()); - $$.subY2.domain($$.y2.domain()); - - // Save original x domain for zoom update - $$.orgXDomain = $$.x.domain(); - - // Set initialized scales to brush and zoom - if ($$.brush) { $$.brush.scale($$.subX); } - if (config.zoom_enabled) { $$.zoom.scale($$.x); } - - /*-- Basic Elements --*/ - - // Define svgs - $$.svg = $$.selectChart.append("svg") - .style("overflow", "hidden") - .on('mouseenter', function () { return config.onmouseover.call($$); }) - .on('mouseleave', function () { return config.onmouseout.call($$); }); - - if ($$.config.svg_classname) { - $$.svg.attr('class', $$.config.svg_classname); - } - - // Define defs - defs = $$.svg.append("defs"); - $$.clipChart = $$.appendClip(defs, $$.clipId); - $$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis); - $$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis); - $$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid); - $$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart); - $$.updateSvgSize(); - - // Define regions - main = $$.main = $$.svg.append("g").attr("transform", $$.getTranslate('main')); - - if ($$.initSubchart) { $$.initSubchart(); } - if ($$.initTooltip) { $$.initTooltip(); } - if ($$.initLegend) { $$.initLegend(); } - if ($$.initTitle) { $$.initTitle(); } - - /*-- Main Region --*/ - - // text when empty - main.append("text") - .attr("class", CLASS.text + ' ' + CLASS.empty) - .attr("text-anchor", "middle") // horizontal centering of text at x position in all browsers. - .attr("dominant-baseline", "middle"); // vertical centering of text at y position in all browsers, except IE. - - // Regions - $$.initRegion(); - - // Grids - $$.initGrid(); - - // Define g for chart area - main.append('g') - .attr("clip-path", $$.clipPath) - .attr('class', CLASS.chart); - - // Grid lines - if (config.grid_lines_front) { $$.initGridLines(); } - - // Cover whole with rects for events - $$.initEventRect(); - - // Define g for chart - $$.initChartElements(); - - // if zoom privileged, insert rect to forefront - // TODO: is this needed? - main.insert('rect', config.zoom_privileged ? null : 'g.' + CLASS.regions) - .attr('class', CLASS.zoomRect) - .attr('width', $$.width) - .attr('height', $$.height) - .style('opacity', 0) - .on("dblclick.zoom", null); - - // Set default extent if defined - if (config.axis_x_extent) { $$.brush.extent($$.getDefaultExtent()); } - - // Add Axis - $$.axis.init(); - - // Set targets - $$.updateTargets($$.data.targets); - - // Draw with targets - if (binding) { - $$.updateDimension(); - $$.config.oninit.call($$); - $$.redraw({ - withTransition: false, - withTransform: true, - withUpdateXDomain: true, - withUpdateOrgXDomain: true, - withTransitionForAxis: false - }); - } - - // Bind resize event - $$.bindResize(); - - // export element of the chart - $$.api.element = $$.selectChart.node(); - }; - - c3_chart_internal_fn.smoothLines = function (el, type) { - var $$ = this; - if (type === 'grid') { - el.each(function () { - var g = $$.d3.select(this), - x1 = g.attr('x1'), - x2 = g.attr('x2'), - y1 = g.attr('y1'), - y2 = g.attr('y2'); - g.attr({ - 'x1': Math.ceil(x1), - 'x2': Math.ceil(x2), - 'y1': Math.ceil(y1), - 'y2': Math.ceil(y2) - }); - }); - } - }; - - - c3_chart_internal_fn.updateSizes = function () { - var $$ = this, config = $$.config; - var legendHeight = $$.legend ? $$.getLegendHeight() : 0, - legendWidth = $$.legend ? $$.getLegendWidth() : 0, - legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight, - hasArc = $$.hasArcType(), - xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'), - subchartHeight = config.subchart_show && !hasArc ? (config.subchart_size_height + xAxisHeight) : 0; - - $$.currentWidth = $$.getCurrentWidth(); - $$.currentHeight = $$.getCurrentHeight(); - - // for main - $$.margin = config.axis_rotated ? { - top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(), - right: hasArc ? 0 : $$.getCurrentPaddingRight(), - bottom: $$.getHorizontalAxisHeight('y') + legendHeightForBottom + $$.getCurrentPaddingBottom(), - left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft()) - } : { - top: 4 + $$.getCurrentPaddingTop(), // for top tick text - right: hasArc ? 0 : $$.getCurrentPaddingRight(), - bottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(), - left: hasArc ? 0 : $$.getCurrentPaddingLeft() - }; - - // for subchart - $$.margin2 = config.axis_rotated ? { - top: $$.margin.top, - right: NaN, - bottom: 20 + legendHeightForBottom, - left: $$.rotated_padding_left - } : { - top: $$.currentHeight - subchartHeight - legendHeightForBottom, - right: NaN, - bottom: xAxisHeight + legendHeightForBottom, - left: $$.margin.left - }; - - // for legend - $$.margin3 = { - top: 0, - right: NaN, - bottom: 0, - left: 0 - }; - if ($$.updateSizeForLegend) { $$.updateSizeForLegend(legendHeight, legendWidth); } - - $$.width = $$.currentWidth - $$.margin.left - $$.margin.right; - $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom; - if ($$.width < 0) { $$.width = 0; } - if ($$.height < 0) { $$.height = 0; } - - $$.width2 = config.axis_rotated ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width; - $$.height2 = config.axis_rotated ? $$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom; - if ($$.width2 < 0) { $$.width2 = 0; } - if ($$.height2 < 0) { $$.height2 = 0; } - - // for arc - $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0); - $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10); - if ($$.hasType('gauge') && !config.gauge_fullCircle) { - $$.arcHeight += $$.height - $$.getGaugeLabelHeight(); - } - if ($$.updateRadius) { $$.updateRadius(); } - - if ($$.isLegendRight && hasArc) { - $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1; - } - }; - - c3_chart_internal_fn.updateTargets = function (targets) { - var $$ = this; - - /*-- Main --*/ - - //-- Text --// - $$.updateTargetsForText(targets); - - //-- Bar --// - $$.updateTargetsForBar(targets); - - //-- Line --// - $$.updateTargetsForLine(targets); - - //-- Arc --// - if ($$.hasArcType() && $$.updateTargetsForArc) { $$.updateTargetsForArc(targets); } - - /*-- Sub --*/ - - if ($$.updateTargetsForSubchart) { $$.updateTargetsForSubchart(targets); } - - // Fade-in each chart - $$.showTargets(); - }; - c3_chart_internal_fn.showTargets = function () { - var $$ = this; - $$.svg.selectAll('.' + CLASS.target).filter(function (d) { return $$.isTargetToShow(d.id); }) - .transition().duration($$.config.transition_duration) - .style("opacity", 1); - }; - - c3_chart_internal_fn.redraw = function (options, transitions) { - var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config; - var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType); - var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, - withTransform, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain, withLegend, - withEventRect, withDimension, withUpdateXAxis; - var hideAxis = $$.hasArcType(); - var drawArea, drawBar, drawLine, xForText, yForText; - var duration, durationForExit, durationForAxis; - var waitForDraw, flow; - var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, i, intervalForCulling, xDomainForZoom; - var xv = $$.xv.bind($$), cx, cy; - - options = options || {}; - withY = getOption(options, "withY", true); - withSubchart = getOption(options, "withSubchart", true); - withTransition = getOption(options, "withTransition", true); - withTransform = getOption(options, "withTransform", false); - withUpdateXDomain = getOption(options, "withUpdateXDomain", false); - withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", false); - withTrimXDomain = getOption(options, "withTrimXDomain", true); - withUpdateXAxis = getOption(options, "withUpdateXAxis", withUpdateXDomain); - withLegend = getOption(options, "withLegend", false); - withEventRect = getOption(options, "withEventRect", true); - withDimension = getOption(options, "withDimension", true); - withTransitionForExit = getOption(options, "withTransitionForExit", withTransition); - withTransitionForAxis = getOption(options, "withTransitionForAxis", withTransition); - - duration = withTransition ? config.transition_duration : 0; - durationForExit = withTransitionForExit ? duration : 0; - durationForAxis = withTransitionForAxis ? duration : 0; - - transitions = transitions || $$.axis.generateTransitions(durationForAxis); - - // update legend and transform each g - if (withLegend && config.legend_show) { - $$.updateLegend($$.mapToIds($$.data.targets), options, transitions); - } else if (withDimension) { - // need to update dimension (e.g. axis.y.tick.values) because y tick values should change - // no need to update axis in it because they will be updated in redraw() - $$.updateDimension(true); - } - - // MEMO: needed for grids calculation - if ($$.isCategorized() && targetsToShow.length === 0) { - $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]); - } - - if (targetsToShow.length) { - $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain); - if (!config.axis_x_tick_values) { - tickValues = $$.axis.updateXAxisTickValues(targetsToShow); - } - } else { - $$.xAxis.tickValues([]); - $$.subXAxis.tickValues([]); - } - - if (config.zoom_rescale && !options.flow) { - xDomainForZoom = $$.x.orgDomain(); - } - - $$.y.domain($$.getYDomain(targetsToShow, 'y', xDomainForZoom)); - $$.y2.domain($$.getYDomain(targetsToShow, 'y2', xDomainForZoom)); - - if (!config.axis_y_tick_values && config.axis_y_tick_count) { - $$.yAxis.tickValues($$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count)); - } - if (!config.axis_y2_tick_values && config.axis_y2_tick_count) { - $$.y2Axis.tickValues($$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count)); - } - - // axes - $$.axis.redraw(transitions, hideAxis); - - // Update axis label - $$.axis.updateLabels(withTransition); - - // show/hide if manual culling needed - if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) { - if (config.axis_x_tick_culling && tickValues) { - for (i = 1; i < tickValues.length; i++) { - if (tickValues.length / i < config.axis_x_tick_culling_max) { - intervalForCulling = i; - break; - } - } - $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) { - var index = tickValues.indexOf(e); - if (index >= 0) { - d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block'); - } - }); - } else { - $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').style('display', 'block'); - } - } - - // setup drawer - MEMO: these must be called after axis updated - drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined; - drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined; - drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined; - xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true); - yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false); - - // Update sub domain - if (withY) { - $$.subY.domain($$.getYDomain(targetsToShow, 'y')); - $$.subY2.domain($$.getYDomain(targetsToShow, 'y2')); - } - - // xgrid focus - $$.updateXgridFocus(); - - // Data empty label positioning and text. - main.select("text." + CLASS.text + '.' + CLASS.empty) - .attr("x", $$.width / 2) - .attr("y", $$.height / 2) - .text(config.data_empty_label_text) - .transition() - .style('opacity', targetsToShow.length ? 0 : 1); - - // grid - $$.updateGrid(duration); - - // rect for regions - $$.updateRegion(duration); - - // bars - $$.updateBar(durationForExit); - - // lines, areas and cricles - $$.updateLine(durationForExit); - $$.updateArea(durationForExit); - $$.updateCircle(); - - // text - if ($$.hasDataLabel()) { - $$.updateText(durationForExit); - } - - // title - if ($$.redrawTitle) { $$.redrawTitle(); } - - // arc - if ($$.redrawArc) { $$.redrawArc(duration, durationForExit, withTransform); } - - // subchart - if ($$.redrawSubchart) { - $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices); - } - - // circles for select - main.selectAll('.' + CLASS.selectedCircles) - .filter($$.isBarType.bind($$)) - .selectAll('circle') - .remove(); - - // event rects will redrawn when flow called - if (config.interaction_enabled && !options.flow && withEventRect) { - $$.redrawEventRect(); - if ($$.updateZoom) { $$.updateZoom(); } - } - - // update circleY based on updated parameters - $$.updateCircleY(); - - // generate circle x/y functions depending on updated params - cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$); - cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$); - - if (options.flow) { - flow = $$.generateFlow({ - targets: targetsToShow, - flow: options.flow, - duration: options.flow.duration, - drawBar: drawBar, - drawLine: drawLine, - drawArea: drawArea, - cx: cx, - cy: cy, - xv: xv, - xForText: xForText, - yForText: yForText - }); - } - - if ((duration || flow) && $$.isTabVisible()) { // Only use transition if tab visible. See #938. - // transition should be derived from one transition - d3.transition().duration(duration).each(function () { - var transitionsToWait = []; - - // redraw and gather transitions - [ - $$.redrawBar(drawBar, true), - $$.redrawLine(drawLine, true), - $$.redrawArea(drawArea, true), - $$.redrawCircle(cx, cy, true), - $$.redrawText(xForText, yForText, options.flow, true), - $$.redrawRegion(true), - $$.redrawGrid(true), - ].forEach(function (transitions) { - transitions.forEach(function (transition) { - transitionsToWait.push(transition); - }); - }); - - // Wait for end of transitions to call flow and onrendered callback - waitForDraw = $$.generateWait(); - transitionsToWait.forEach(function (t) { - waitForDraw.add(t); - }); - }) - .call(waitForDraw, function () { - if (flow) { - flow(); - } - if (config.onrendered) { - config.onrendered.call($$); - } - }); - } - else { - $$.redrawBar(drawBar); - $$.redrawLine(drawLine); - $$.redrawArea(drawArea); - $$.redrawCircle(cx, cy); - $$.redrawText(xForText, yForText, options.flow); - $$.redrawRegion(); - $$.redrawGrid(); - if (config.onrendered) { - config.onrendered.call($$); - } - } - - // update fadein condition - $$.mapToIds($$.data.targets).forEach(function (id) { - $$.withoutFadeIn[id] = true; - }); - }; - - c3_chart_internal_fn.updateAndRedraw = function (options) { - var $$ = this, config = $$.config, transitions; - options = options || {}; - // same with redraw - options.withTransition = getOption(options, "withTransition", true); - options.withTransform = getOption(options, "withTransform", false); - options.withLegend = getOption(options, "withLegend", false); - // NOT same with redraw - options.withUpdateXDomain = true; - options.withUpdateOrgXDomain = true; - options.withTransitionForExit = false; - options.withTransitionForTransform = getOption(options, "withTransitionForTransform", options.withTransition); - // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called) - $$.updateSizes(); - // MEMO: called in updateLegend in redraw if withLegend - if (!(options.withLegend && config.legend_show)) { - transitions = $$.axis.generateTransitions(options.withTransitionForAxis ? config.transition_duration : 0); - // Update scales - $$.updateScales(); - $$.updateSvgSize(); - // Update g positions - $$.transformAll(options.withTransitionForTransform, transitions); - } - // Draw with new sizes & scales - $$.redraw(options, transitions); - }; - c3_chart_internal_fn.redrawWithoutRescale = function () { - this.redraw({ - withY: false, - withSubchart: false, - withEventRect: false, - withTransitionForAxis: false - }); - }; - - c3_chart_internal_fn.isTimeSeries = function () { - return this.config.axis_x_type === 'timeseries'; - }; - c3_chart_internal_fn.isCategorized = function () { - return this.config.axis_x_type.indexOf('categor') >= 0; - }; - c3_chart_internal_fn.isCustomX = function () { - var $$ = this, config = $$.config; - return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs)); - }; - - c3_chart_internal_fn.isTimeSeriesY = function () { - return this.config.axis_y_type === 'timeseries'; - }; - - c3_chart_internal_fn.getTranslate = function (target) { - var $$ = this, config = $$.config, x, y; - if (target === 'main') { - x = asHalfPixel($$.margin.left); - y = asHalfPixel($$.margin.top); - } else if (target === 'context') { - x = asHalfPixel($$.margin2.left); - y = asHalfPixel($$.margin2.top); - } else if (target === 'legend') { - x = $$.margin3.left; - y = $$.margin3.top; - } else if (target === 'x') { - x = 0; - y = config.axis_rotated ? 0 : $$.height; - } else if (target === 'y') { - x = 0; - y = config.axis_rotated ? $$.height : 0; - } else if (target === 'y2') { - x = config.axis_rotated ? 0 : $$.width; - y = config.axis_rotated ? 1 : 0; - } else if (target === 'subx') { - x = 0; - y = config.axis_rotated ? 0 : $$.height2; - } else if (target === 'arc') { - x = $$.arcWidth / 2; - y = $$.arcHeight / 2; - } - return "translate(" + x + "," + y + ")"; - }; - c3_chart_internal_fn.initialOpacity = function (d) { - return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0; - }; - c3_chart_internal_fn.initialOpacityForCircle = function (d) { - return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0; - }; - c3_chart_internal_fn.opacityForCircle = function (d) { - var opacity = this.config.point_show ? 1 : 0; - return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0; - }; - c3_chart_internal_fn.opacityForText = function () { - return this.hasDataLabel() ? 1 : 0; - }; - c3_chart_internal_fn.xx = function (d) { - return d ? this.x(d.x) : null; - }; - c3_chart_internal_fn.xv = function (d) { - var $$ = this, value = d.value; - if ($$.isTimeSeries()) { - value = $$.parseDate(d.value); - } - else if ($$.isCategorized() && typeof d.value === 'string') { - value = $$.config.axis_x_categories.indexOf(d.value); - } - return Math.ceil($$.x(value)); - }; - c3_chart_internal_fn.yv = function (d) { - var $$ = this, - yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y; - return Math.ceil(yScale(d.value)); - }; - c3_chart_internal_fn.subxx = function (d) { - return d ? this.subX(d.x) : null; - }; - - c3_chart_internal_fn.transformMain = function (withTransition, transitions) { - var $$ = this, - xAxis, yAxis, y2Axis; - if (transitions && transitions.axisX) { - xAxis = transitions.axisX; - } else { - xAxis = $$.main.select('.' + CLASS.axisX); - if (withTransition) { xAxis = xAxis.transition(); } - } - if (transitions && transitions.axisY) { - yAxis = transitions.axisY; - } else { - yAxis = $$.main.select('.' + CLASS.axisY); - if (withTransition) { yAxis = yAxis.transition(); } - } - if (transitions && transitions.axisY2) { - y2Axis = transitions.axisY2; - } else { - y2Axis = $$.main.select('.' + CLASS.axisY2); - if (withTransition) { y2Axis = y2Axis.transition(); } - } - (withTransition ? $$.main.transition() : $$.main).attr("transform", $$.getTranslate('main')); - xAxis.attr("transform", $$.getTranslate('x')); - yAxis.attr("transform", $$.getTranslate('y')); - y2Axis.attr("transform", $$.getTranslate('y2')); - $$.main.select('.' + CLASS.chartArcs).attr("transform", $$.getTranslate('arc')); - }; - c3_chart_internal_fn.transformAll = function (withTransition, transitions) { - var $$ = this; - $$.transformMain(withTransition, transitions); - if ($$.config.subchart_show) { $$.transformContext(withTransition, transitions); } - if ($$.legend) { $$.transformLegend(withTransition); } - }; - - c3_chart_internal_fn.updateSvgSize = function () { - var $$ = this, - brush = $$.svg.select(".c3-brush .background"); - $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight); - $$.svg.selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid]).select('rect') - .attr('width', $$.width) - .attr('height', $$.height); - $$.svg.select('#' + $$.clipIdForXAxis).select('rect') - .attr('x', $$.getXAxisClipX.bind($$)) - .attr('y', $$.getXAxisClipY.bind($$)) - .attr('width', $$.getXAxisClipWidth.bind($$)) - .attr('height', $$.getXAxisClipHeight.bind($$)); - $$.svg.select('#' + $$.clipIdForYAxis).select('rect') - .attr('x', $$.getYAxisClipX.bind($$)) - .attr('y', $$.getYAxisClipY.bind($$)) - .attr('width', $$.getYAxisClipWidth.bind($$)) - .attr('height', $$.getYAxisClipHeight.bind($$)); - $$.svg.select('#' + $$.clipIdForSubchart).select('rect') - .attr('width', $$.width) - .attr('height', brush.size() ? brush.attr('height') : 0); - $$.svg.select('.' + CLASS.zoomRect) - .attr('width', $$.width) - .attr('height', $$.height); - // MEMO: parent div's height will be bigger than svg when - $$.selectChart.style('max-height', $$.currentHeight + "px"); - }; - - - c3_chart_internal_fn.updateDimension = function (withoutAxis) { - var $$ = this; - if (!withoutAxis) { - if ($$.config.axis_rotated) { - $$.axes.x.call($$.xAxis); - $$.axes.subx.call($$.subXAxis); - } else { - $$.axes.y.call($$.yAxis); - $$.axes.y2.call($$.y2Axis); - } - } - $$.updateSizes(); - $$.updateScales(); - $$.updateSvgSize(); - $$.transformAll(false); - }; - - c3_chart_internal_fn.observeInserted = function (selection) { - var $$ = this, observer; - if (typeof MutationObserver === 'undefined') { - window.console.error("MutationObserver not defined."); - return; - } - observer= new MutationObserver(function (mutations) { - mutations.forEach(function (mutation) { - if (mutation.type === 'childList' && mutation.previousSibling) { - observer.disconnect(); - // need to wait for completion of load because size calculation requires the actual sizes determined after that completion - $$.intervalForObserveInserted = window.setInterval(function () { - // parentNode will NOT be null when completed - if (selection.node().parentNode) { - window.clearInterval($$.intervalForObserveInserted); - $$.updateDimension(); - if ($$.brush) { $$.brush.update(); } - $$.config.oninit.call($$); - $$.redraw({ - withTransform: true, - withUpdateXDomain: true, - withUpdateOrgXDomain: true, - withTransition: false, - withTransitionForTransform: false, - withLegend: true - }); - selection.transition().style('opacity', 1); - } - }, 10); - } - }); - }); - observer.observe(selection.node(), {attributes: true, childList: true, characterData: true}); - }; - - c3_chart_internal_fn.bindResize = function () { - var $$ = this, config = $$.config; - - $$.resizeFunction = $$.generateResize(); - - $$.resizeFunction.add(function () { - config.onresize.call($$); - }); - if (config.resize_auto) { - $$.resizeFunction.add(function () { - if ($$.resizeTimeout !== undefined) { - window.clearTimeout($$.resizeTimeout); - } - $$.resizeTimeout = window.setTimeout(function () { - delete $$.resizeTimeout; - $$.api.flush(); - }, 100); - }); - } - $$.resizeFunction.add(function () { - config.onresized.call($$); - }); - - if (window.attachEvent) { - window.attachEvent('onresize', $$.resizeFunction); - } else if (window.addEventListener) { - window.addEventListener('resize', $$.resizeFunction, false); - } else { - // fallback to this, if this is a very old browser - var wrapper = window.onresize; - if (!wrapper) { - // create a wrapper that will call all charts - wrapper = $$.generateResize(); - } else if (!wrapper.add || !wrapper.remove) { - // there is already a handler registered, make sure we call it too - wrapper = $$.generateResize(); - wrapper.add(window.onresize); - } - // add this graph to the wrapper, we will be removed if the user calls destroy - wrapper.add($$.resizeFunction); - window.onresize = wrapper; - } - }; - - c3_chart_internal_fn.generateResize = function () { - var resizeFunctions = []; - function callResizeFunctions() { - resizeFunctions.forEach(function (f) { - f(); - }); - } - callResizeFunctions.add = function (f) { - resizeFunctions.push(f); - }; - callResizeFunctions.remove = function (f) { - for (var i = 0; i < resizeFunctions.length; i++) { - if (resizeFunctions[i] === f) { - resizeFunctions.splice(i, 1); - break; - } - } - }; - return callResizeFunctions; - }; - - c3_chart_internal_fn.endall = function (transition, callback) { - var n = 0; - transition - .each(function () { ++n; }) - .each("end", function () { - if (!--n) { callback.apply(this, arguments); } - }); - }; - c3_chart_internal_fn.generateWait = function () { - var transitionsToWait = [], - f = function (transition, callback) { - var timer = setInterval(function () { - var done = 0; - transitionsToWait.forEach(function (t) { - if (t.empty()) { - done += 1; - return; - } - try { - t.transition(); - } catch (e) { - done += 1; - } - }); - if (done === transitionsToWait.length) { - clearInterval(timer); - if (callback) { callback(); } - } - }, 10); - }; - f.add = function (transition) { - transitionsToWait.push(transition); - }; - return f; - }; - - c3_chart_internal_fn.parseDate = function (date) { - var $$ = this, parsedDate; - if (date instanceof Date) { - parsedDate = date; - } else if (typeof date === 'string') { - parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date); - } else if (typeof date === 'number' && !isNaN(date)) { - parsedDate = new Date(+date); - } - if (!parsedDate || isNaN(+parsedDate)) { - window.console.error("Failed to parse x '" + date + "' to Date object"); - } - return parsedDate; - }; - - c3_chart_internal_fn.isTabVisible = function () { - var hidden; - if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support - hidden = "hidden"; - } else if (typeof document.mozHidden !== "undefined") { - hidden = "mozHidden"; - } else if (typeof document.msHidden !== "undefined") { - hidden = "msHidden"; - } else if (typeof document.webkitHidden !== "undefined") { - hidden = "webkitHidden"; - } - - return document[hidden] ? false : true; - }; - - c3_chart_internal_fn.getDefaultConfig = function () { - var config = { - bindto: '#chart', - svg_classname: undefined, - size_width: undefined, - size_height: undefined, - padding_left: undefined, - padding_right: undefined, - padding_top: undefined, - padding_bottom: undefined, - resize_auto: true, - zoom_enabled: false, - zoom_extent: undefined, - zoom_privileged: false, - zoom_rescale: false, - zoom_onzoom: function () {}, - zoom_onzoomstart: function () {}, - zoom_onzoomend: function () {}, - zoom_x_min: undefined, - zoom_x_max: undefined, - interaction_brighten: true, - interaction_enabled: true, - onmouseover: function () {}, - onmouseout: function () {}, - onresize: function () {}, - onresized: function () {}, - oninit: function () {}, - onrendered: function () {}, - transition_duration: 350, - data_x: undefined, - data_xs: {}, - data_xFormat: '%Y-%m-%d', - data_xLocaltime: true, - data_xSort: true, - data_idConverter: function (id) { return id; }, - data_names: {}, - data_classes: {}, - data_groups: [], - data_axes: {}, - data_type: undefined, - data_types: {}, - data_labels: {}, - data_order: 'desc', - data_regions: {}, - data_color: undefined, - data_colors: {}, - data_hide: false, - data_filter: undefined, - data_selection_enabled: false, - data_selection_grouped: false, - data_selection_isselectable: function () { return true; }, - data_selection_multiple: true, - data_selection_draggable: false, - data_onclick: function () {}, - data_onmouseover: function () {}, - data_onmouseout: function () {}, - data_onselected: function () {}, - data_onunselected: function () {}, - data_url: undefined, - data_headers: undefined, - data_json: undefined, - data_rows: undefined, - data_columns: undefined, - data_mimeType: undefined, - data_keys: undefined, - // configuration for no plot-able data supplied. - data_empty_label_text: "", - // subchart - subchart_show: false, - subchart_size_height: 60, - subchart_axis_x_show: true, - subchart_onbrush: function () {}, - // color - color_pattern: [], - color_threshold: {}, - // legend - legend_show: true, - legend_hide: false, - legend_position: 'bottom', - legend_inset_anchor: 'top-left', - legend_inset_x: 10, - legend_inset_y: 0, - legend_inset_step: undefined, - legend_item_onclick: undefined, - legend_item_onmouseover: undefined, - legend_item_onmouseout: undefined, - legend_equally: false, - legend_padding: 0, - legend_item_tile_width: 10, - legend_item_tile_height: 10, - // axis - axis_rotated: false, - axis_x_show: true, - axis_x_type: 'indexed', - axis_x_localtime: true, - axis_x_categories: [], - axis_x_tick_centered: false, - axis_x_tick_format: undefined, - axis_x_tick_culling: {}, - axis_x_tick_culling_max: 10, - axis_x_tick_count: undefined, - axis_x_tick_fit: true, - axis_x_tick_values: null, - axis_x_tick_rotate: 0, - axis_x_tick_outer: true, - axis_x_tick_multiline: true, - axis_x_tick_width: null, - axis_x_max: undefined, - axis_x_min: undefined, - axis_x_padding: {}, - axis_x_height: undefined, - axis_x_extent: undefined, - axis_x_label: {}, - axis_y_show: true, - axis_y_type: undefined, - axis_y_max: undefined, - axis_y_min: undefined, - axis_y_inverted: false, - axis_y_center: undefined, - axis_y_inner: undefined, - axis_y_label: {}, - axis_y_tick_format: undefined, - axis_y_tick_outer: true, - axis_y_tick_values: null, - axis_y_tick_rotate: 0, - axis_y_tick_count: undefined, - axis_y_tick_time_value: undefined, - axis_y_tick_time_interval: undefined, - axis_y_padding: {}, - axis_y_default: undefined, - axis_y2_show: false, - axis_y2_max: undefined, - axis_y2_min: undefined, - axis_y2_inverted: false, - axis_y2_center: undefined, - axis_y2_inner: undefined, - axis_y2_label: {}, - axis_y2_tick_format: undefined, - axis_y2_tick_outer: true, - axis_y2_tick_values: null, - axis_y2_tick_count: undefined, - axis_y2_padding: {}, - axis_y2_default: undefined, - // grid - grid_x_show: false, - grid_x_type: 'tick', - grid_x_lines: [], - grid_y_show: false, - // not used - // grid_y_type: 'tick', - grid_y_lines: [], - grid_y_ticks: 10, - grid_focus_show: true, - grid_lines_front: true, - // point - point of each data - point_show: true, - point_r: 2.5, - point_sensitivity: 10, - point_focus_expand_enabled: true, - point_focus_expand_r: undefined, - point_select_r: undefined, - // line - line_connectNull: false, - line_step_type: 'step', - // bar - bar_width: undefined, - bar_width_ratio: 0.6, - bar_width_max: undefined, - bar_zerobased: true, - // area - area_zerobased: true, - area_above: false, - // pie - pie_label_show: true, - pie_label_format: undefined, - pie_label_threshold: 0.05, - pie_label_ratio: undefined, - pie_expand: {}, - pie_expand_duration: 50, - // gauge - gauge_fullCircle: false, - gauge_label_show: true, - gauge_label_format: undefined, - gauge_min: 0, - gauge_max: 100, - gauge_startingAngle: -1 * Math.PI/2, - gauge_units: undefined, - gauge_width: undefined, - gauge_expand: {}, - gauge_expand_duration: 50, - // donut - donut_label_show: true, - donut_label_format: undefined, - donut_label_threshold: 0.05, - donut_label_ratio: undefined, - donut_width: undefined, - donut_title: "", - donut_expand: {}, - donut_expand_duration: 50, - // spline - spline_interpolation_type: 'cardinal', - // region - region to change style - regions: [], - // tooltip - show when mouseover on each data - tooltip_show: true, - tooltip_grouped: true, - tooltip_format_title: undefined, - tooltip_format_name: undefined, - tooltip_format_value: undefined, - tooltip_position: undefined, - tooltip_contents: function (d, defaultTitleFormat, defaultValueFormat, color) { - return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : ''; - }, - tooltip_init_show: false, - tooltip_init_x: 0, - tooltip_init_position: {top: '0px', left: '50px'}, - tooltip_onshow: function () {}, - tooltip_onhide: function () {}, - // title - title_text: undefined, - title_padding: { - top: 0, - right: 0, - bottom: 0, - left: 0 - }, - title_position: 'top-center', - }; - - Object.keys(this.additionalConfig).forEach(function (key) { - config[key] = this.additionalConfig[key]; - }, this); - - return config; - }; - c3_chart_internal_fn.additionalConfig = {}; - - c3_chart_internal_fn.loadConfig = function (config) { - var this_config = this.config, target, keys, read; - function find() { - var key = keys.shift(); - // console.log("key =>", key, ", target =>", target); - if (key && target && typeof target === 'object' && key in target) { - target = target[key]; - return find(); - } - else if (!key) { - return target; - } - else { - return undefined; - } - } - Object.keys(this_config).forEach(function (key) { - target = config; - keys = key.split('_'); - read = find(); - // console.log("CONFIG : ", key, read); - if (isDefined(read)) { - this_config[key] = read; - } - }); - }; - - c3_chart_internal_fn.getScale = function (min, max, forTimeseries) { - return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]); - }; - c3_chart_internal_fn.getX = function (min, max, domain, offset) { - var $$ = this, - scale = $$.getScale(min, max, $$.isTimeSeries()), - _scale = domain ? scale.domain(domain) : scale, key; - // Define customized scale if categorized axis - if ($$.isCategorized()) { - offset = offset || function () { return 0; }; - scale = function (d, raw) { - var v = _scale(d) + offset(d); - return raw ? v : Math.ceil(v); - }; - } else { - scale = function (d, raw) { - var v = _scale(d); - return raw ? v : Math.ceil(v); - }; - } - // define functions - for (key in _scale) { - scale[key] = _scale[key]; - } - scale.orgDomain = function () { - return _scale.domain(); - }; - // define custom domain() for categorized axis - if ($$.isCategorized()) { - scale.domain = function (domain) { - if (!arguments.length) { - domain = this.orgDomain(); - return [domain[0], domain[1] + 1]; - } - _scale.domain(domain); - return scale; - }; - } - return scale; - }; - c3_chart_internal_fn.getY = function (min, max, domain) { - var scale = this.getScale(min, max, this.isTimeSeriesY()); - if (domain) { scale.domain(domain); } - return scale; - }; - c3_chart_internal_fn.getYScale = function (id) { - return this.axis.getId(id) === 'y2' ? this.y2 : this.y; - }; - c3_chart_internal_fn.getSubYScale = function (id) { - return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY; - }; - c3_chart_internal_fn.updateScales = function () { - var $$ = this, config = $$.config, - forInit = !$$.x; - // update edges - $$.xMin = config.axis_rotated ? 1 : 0; - $$.xMax = config.axis_rotated ? $$.height : $$.width; - $$.yMin = config.axis_rotated ? 0 : $$.height; - $$.yMax = config.axis_rotated ? $$.width : 1; - $$.subXMin = $$.xMin; - $$.subXMax = $$.xMax; - $$.subYMin = config.axis_rotated ? 0 : $$.height2; - $$.subYMax = config.axis_rotated ? $$.width2 : 1; - // update scales - $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () { return $$.xAxis.tickOffset(); }); - $$.y = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y_default : $$.y.domain()); - $$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y2_default : $$.y2.domain()); - $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) { return d % 1 ? 0 : $$.subXAxis.tickOffset(); }); - $$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y_default : $$.subY.domain()); - $$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y2_default : $$.subY2.domain()); - // update axes - $$.xAxisTickFormat = $$.axis.getXAxisTickFormat(); - $$.xAxisTickValues = $$.axis.getXAxisTickValues(); - $$.yAxisTickValues = $$.axis.getYAxisTickValues(); - $$.y2AxisTickValues = $$.axis.getY2AxisTickValues(); - - $$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer); - $$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer); - $$.yAxis = $$.axis.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, config.axis_y_tick_outer); - $$.y2Axis = $$.axis.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, config.axis_y2_tick_outer); - - // Set initialized scales to brush and zoom - if (!forInit) { - if ($$.brush) { $$.brush.scale($$.subX); } - if (config.zoom_enabled) { $$.zoom.scale($$.x); } - } - // update for arc - if ($$.updateArc) { $$.updateArc(); } - }; - - c3_chart_internal_fn.getYDomainMin = function (targets) { - var $$ = this, config = $$.config, - ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), - j, k, baseId, idsInGroup, id, hasNegativeValue; - if (config.data_groups.length > 0) { - hasNegativeValue = $$.hasNegativeValueInTargets(targets); - for (j = 0; j < config.data_groups.length; j++) { - // Determine baseId - idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; }); - if (idsInGroup.length === 0) { continue; } - baseId = idsInGroup[0]; - // Consider negative values - if (hasNegativeValue && ys[baseId]) { - ys[baseId].forEach(function (v, i) { - ys[baseId][i] = v < 0 ? v : 0; - }); - } - // Compute min - for (k = 1; k < idsInGroup.length; k++) { - id = idsInGroup[k]; - if (! ys[id]) { continue; } - ys[id].forEach(function (v, i) { - if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) { - ys[baseId][i] += +v; - } - }); - } - } - } - return $$.d3.min(Object.keys(ys).map(function (key) { return $$.d3.min(ys[key]); })); - }; - c3_chart_internal_fn.getYDomainMax = function (targets) { - var $$ = this, config = $$.config, - ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), - j, k, baseId, idsInGroup, id, hasPositiveValue; - if (config.data_groups.length > 0) { - hasPositiveValue = $$.hasPositiveValueInTargets(targets); - for (j = 0; j < config.data_groups.length; j++) { - // Determine baseId - idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; }); - if (idsInGroup.length === 0) { continue; } - baseId = idsInGroup[0]; - // Consider positive values - if (hasPositiveValue && ys[baseId]) { - ys[baseId].forEach(function (v, i) { - ys[baseId][i] = v > 0 ? v : 0; - }); - } - // Compute max - for (k = 1; k < idsInGroup.length; k++) { - id = idsInGroup[k]; - if (! ys[id]) { continue; } - ys[id].forEach(function (v, i) { - if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) { - ys[baseId][i] += +v; - } - }); - } - } - } - return $$.d3.max(Object.keys(ys).map(function (key) { return $$.d3.max(ys[key]); })); - }; - c3_chart_internal_fn.getYDomain = function (targets, axisId, xDomain) { - var $$ = this, config = $$.config, - targetsByAxisId = targets.filter(function (t) { return $$.axis.getId(t.id) === axisId; }), - yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId, - yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min, - yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max, - yDomainMin = $$.getYDomainMin(yTargets), - yDomainMax = $$.getYDomainMax(yTargets), - domain, domainLength, padding, padding_top, padding_bottom, - center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center, - yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative, - isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) || ($$.hasType('area', yTargets) && config.area_zerobased), - isInverted = axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted, - showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated, - showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated; - - // MEMO: avoid inverting domain unexpectedly - yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? (yDomainMin < yMax ? yDomainMin : yMax - 10) : yDomainMin; - yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? (yMin < yDomainMax ? yDomainMax : yMin + 10) : yDomainMax; - - if (yTargets.length === 0) { // use current domain if target of axisId is none - return axisId === 'y2' ? $$.y2.domain() : $$.y.domain(); - } - if (isNaN(yDomainMin)) { // set minimum to zero when not number - yDomainMin = 0; - } - if (isNaN(yDomainMax)) { // set maximum to have same value as yDomainMin - yDomainMax = yDomainMin; - } - if (yDomainMin === yDomainMax) { - yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0; - } - isAllPositive = yDomainMin >= 0 && yDomainMax >= 0; - isAllNegative = yDomainMin <= 0 && yDomainMax <= 0; - - // Cancel zerobased if axis_*_min / axis_*_max specified - if ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) { - isZeroBased = false; - } - - // Bar/Area chart should be 0-based if all positive|negative - if (isZeroBased) { - if (isAllPositive) { yDomainMin = 0; } - if (isAllNegative) { yDomainMax = 0; } - } - - domainLength = Math.abs(yDomainMax - yDomainMin); - padding = padding_top = padding_bottom = domainLength * 0.1; - - if (typeof center !== 'undefined') { - yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax)); - yDomainMax = center + yDomainAbs; - yDomainMin = center - yDomainAbs; - } - // add padding for data label - if (showHorizontalDataLabel) { - lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width'); - diff = diffDomain($$.y.range()); - ratio = [lengths[0] / diff, lengths[1] / diff]; - padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1])); - padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1])); - } else if (showVerticalDataLabel) { - lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height'); - padding_top += $$.axis.convertPixelsToAxisPadding(lengths[1], domainLength); - padding_bottom += $$.axis.convertPixelsToAxisPadding(lengths[0], domainLength); - } - if (axisId === 'y' && notEmpty(config.axis_y_padding)) { - padding_top = $$.axis.getPadding(config.axis_y_padding, 'top', padding_top, domainLength); - padding_bottom = $$.axis.getPadding(config.axis_y_padding, 'bottom', padding_bottom, domainLength); - } - if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) { - padding_top = $$.axis.getPadding(config.axis_y2_padding, 'top', padding_top, domainLength); - padding_bottom = $$.axis.getPadding(config.axis_y2_padding, 'bottom', padding_bottom, domainLength); - } - // Bar/Area chart should be 0-based if all positive|negative - if (isZeroBased) { - if (isAllPositive) { padding_bottom = yDomainMin; } - if (isAllNegative) { padding_top = -yDomainMax; } - } - domain = [yDomainMin - padding_bottom, yDomainMax + padding_top]; - return isInverted ? domain.reverse() : domain; - }; - c3_chart_internal_fn.getXDomainMin = function (targets) { - var $$ = this, config = $$.config; - return isDefined(config.axis_x_min) ? - ($$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min) : - $$.d3.min(targets, function (t) { return $$.d3.min(t.values, function (v) { return v.x; }); }); - }; - c3_chart_internal_fn.getXDomainMax = function (targets) { - var $$ = this, config = $$.config; - return isDefined(config.axis_x_max) ? - ($$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max) : - $$.d3.max(targets, function (t) { return $$.d3.max(t.values, function (v) { return v.x; }); }); - }; - c3_chart_internal_fn.getXDomainPadding = function (domain) { - var $$ = this, config = $$.config, - diff = domain[1] - domain[0], - maxDataCount, padding, paddingLeft, paddingRight; - if ($$.isCategorized()) { - padding = 0; - } else if ($$.hasType('bar')) { - maxDataCount = $$.getMaxDataCount(); - padding = maxDataCount > 1 ? (diff / (maxDataCount - 1)) / 2 : 0.5; - } else { - padding = diff * 0.01; - } - if (typeof config.axis_x_padding === 'object' && notEmpty(config.axis_x_padding)) { - paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding; - paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding; - } else if (typeof config.axis_x_padding === 'number') { - paddingLeft = paddingRight = config.axis_x_padding; - } else { - paddingLeft = paddingRight = padding; - } - return {left: paddingLeft, right: paddingRight}; - }; - c3_chart_internal_fn.getXDomain = function (targets) { - var $$ = this, - xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)], - firstX = xDomain[0], lastX = xDomain[1], - padding = $$.getXDomainPadding(xDomain), - min = 0, max = 0; - // show center of x domain if min and max are the same - if ((firstX - lastX) === 0 && !$$.isCategorized()) { - if ($$.isTimeSeries()) { - firstX = new Date(firstX.getTime() * 0.5); - lastX = new Date(lastX.getTime() * 1.5); - } else { - firstX = firstX === 0 ? 1 : (firstX * 0.5); - lastX = lastX === 0 ? -1 : (lastX * 1.5); - } - } - if (firstX || firstX === 0) { - min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left; - } - if (lastX || lastX === 0) { - max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right; - } - return [min, max]; - }; - c3_chart_internal_fn.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) { - var $$ = this, config = $$.config; - - if (withUpdateOrgXDomain) { - $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets))); - $$.orgXDomain = $$.x.domain(); - if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); } - $$.subX.domain($$.x.domain()); - if ($$.brush) { $$.brush.scale($$.subX); } - } - if (withUpdateXDomain) { - $$.x.domain(domain ? domain : (!$$.brush || $$.brush.empty()) ? $$.orgXDomain : $$.brush.extent()); - if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); } - } - - // Trim domain when too big by zoom mousemove event - if (withTrim) { $$.x.domain($$.trimXDomain($$.x.orgDomain())); } - - return $$.x.domain(); - }; - c3_chart_internal_fn.trimXDomain = function (domain) { - var zoomDomain = this.getZoomDomain(), - min = zoomDomain[0], max = zoomDomain[1]; - if (domain[0] <= min) { - domain[1] = +domain[1] + (min - domain[0]); - domain[0] = min; - } - if (max <= domain[1]) { - domain[0] = +domain[0] - (domain[1] - max); - domain[1] = max; - } - return domain; - }; - - c3_chart_internal_fn.isX = function (key) { - var $$ = this, config = $$.config; - return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key)); - }; - c3_chart_internal_fn.isNotX = function (key) { - return !this.isX(key); - }; - c3_chart_internal_fn.getXKey = function (id) { - var $$ = this, config = $$.config; - return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null; - }; - c3_chart_internal_fn.getXValuesOfXKey = function (key, targets) { - var $$ = this, - xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : []; - ids.forEach(function (id) { - if ($$.getXKey(id) === key) { - xValues = $$.data.xs[id]; - } - }); - return xValues; - }; - c3_chart_internal_fn.getIndexByX = function (x) { - var $$ = this, - data = $$.filterByX($$.data.targets, x); - return data.length ? data[0].index : null; - }; - c3_chart_internal_fn.getXValue = function (id, i) { - var $$ = this; - return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i; - }; - c3_chart_internal_fn.getOtherTargetXs = function () { - var $$ = this, - idsForX = Object.keys($$.data.xs); - return idsForX.length ? $$.data.xs[idsForX[0]] : null; - }; - c3_chart_internal_fn.getOtherTargetX = function (index) { - var xs = this.getOtherTargetXs(); - return xs && index < xs.length ? xs[index] : null; - }; - c3_chart_internal_fn.addXs = function (xs) { - var $$ = this; - Object.keys(xs).forEach(function (id) { - $$.config.data_xs[id] = xs[id]; - }); - }; - c3_chart_internal_fn.hasMultipleX = function (xs) { - return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() > 1; - }; - c3_chart_internal_fn.isMultipleX = function () { - return notEmpty(this.config.data_xs) || !this.config.data_xSort || this.hasType('scatter'); - }; - c3_chart_internal_fn.addName = function (data) { - var $$ = this, name; - if (data) { - name = $$.config.data_names[data.id]; - data.name = name !== undefined ? name : data.id; - } - return data; - }; - c3_chart_internal_fn.getValueOnIndex = function (values, index) { - var valueOnIndex = values.filter(function (v) { return v.index === index; }); - return valueOnIndex.length ? valueOnIndex[0] : null; - }; - c3_chart_internal_fn.updateTargetX = function (targets, x) { - var $$ = this; - targets.forEach(function (t) { - t.values.forEach(function (v, i) { - v.x = $$.generateTargetX(x[i], t.id, i); - }); - $$.data.xs[t.id] = x; - }); - }; - c3_chart_internal_fn.updateTargetXs = function (targets, xs) { - var $$ = this; - targets.forEach(function (t) { - if (xs[t.id]) { - $$.updateTargetX([t], xs[t.id]); - } - }); - }; - c3_chart_internal_fn.generateTargetX = function (rawX, id, index) { - var $$ = this, x; - if ($$.isTimeSeries()) { - x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index)); - } - else if ($$.isCustomX() && !$$.isCategorized()) { - x = isValue(rawX) ? +rawX : $$.getXValue(id, index); - } - else { - x = index; - } - return x; - }; - c3_chart_internal_fn.cloneTarget = function (target) { - return { - id : target.id, - id_org : target.id_org, - values : target.values.map(function (d) { - return {x: d.x, value: d.value, id: d.id}; - }) - }; - }; - c3_chart_internal_fn.updateXs = function () { - var $$ = this; - if ($$.data.targets.length) { - $$.xs = []; - $$.data.targets[0].values.forEach(function (v) { - $$.xs[v.index] = v.x; - }); - } - }; - c3_chart_internal_fn.getPrevX = function (i) { - var x = this.xs[i - 1]; - return typeof x !== 'undefined' ? x : null; - }; - c3_chart_internal_fn.getNextX = function (i) { - var x = this.xs[i + 1]; - return typeof x !== 'undefined' ? x : null; - }; - c3_chart_internal_fn.getMaxDataCount = function () { - var $$ = this; - return $$.d3.max($$.data.targets, function (t) { return t.values.length; }); - }; - c3_chart_internal_fn.getMaxDataCountTarget = function (targets) { - var length = targets.length, max = 0, maxTarget; - if (length > 1) { - targets.forEach(function (t) { - if (t.values.length > max) { - maxTarget = t; - max = t.values.length; - } - }); - } else { - maxTarget = length ? targets[0] : null; - } - return maxTarget; - }; - c3_chart_internal_fn.getEdgeX = function (targets) { - var $$ = this; - return !targets.length ? [0, 0] : [ - $$.d3.min(targets, function (t) { return t.values[0].x; }), - $$.d3.max(targets, function (t) { return t.values[t.values.length - 1].x; }) - ]; - }; - c3_chart_internal_fn.mapToIds = function (targets) { - return targets.map(function (d) { return d.id; }); - }; - c3_chart_internal_fn.mapToTargetIds = function (ids) { - var $$ = this; - return ids ? [].concat(ids) : $$.mapToIds($$.data.targets); - }; - c3_chart_internal_fn.hasTarget = function (targets, id) { - var ids = this.mapToIds(targets), i; - for (i = 0; i < ids.length; i++) { - if (ids[i] === id) { - return true; - } - } - return false; - }; - c3_chart_internal_fn.isTargetToShow = function (targetId) { - return this.hiddenTargetIds.indexOf(targetId) < 0; - }; - c3_chart_internal_fn.isLegendToShow = function (targetId) { - return this.hiddenLegendIds.indexOf(targetId) < 0; - }; - c3_chart_internal_fn.filterTargetsToShow = function (targets) { - var $$ = this; - return targets.filter(function (t) { return $$.isTargetToShow(t.id); }); - }; - c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) { - var $$ = this; - var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return +v.x; }); }))).values(); - xs = $$.isTimeSeries() ? xs.map(function (x) { return new Date(+x); }) : xs.map(function (x) { return +x; }); - return xs.sort(function (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; }); - }; - c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) { - this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds); - }; - c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) { - this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); - }; - c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) { - this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds); - }; - c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) { - this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); - }; - c3_chart_internal_fn.getValuesAsIdKeyed = function (targets) { - var ys = {}; - targets.forEach(function (t) { - ys[t.id] = []; - t.values.forEach(function (v) { - ys[t.id].push(v.value); - }); - }); - return ys; - }; - c3_chart_internal_fn.checkValueInTargets = function (targets, checker) { - var ids = Object.keys(targets), i, j, values; - for (i = 0; i < ids.length; i++) { - values = targets[ids[i]].values; - for (j = 0; j < values.length; j++) { - if (checker(values[j].value)) { - return true; - } - } - } - return false; - }; - c3_chart_internal_fn.hasNegativeValueInTargets = function (targets) { - return this.checkValueInTargets(targets, function (v) { return v < 0; }); - }; - c3_chart_internal_fn.hasPositiveValueInTargets = function (targets) { - return this.checkValueInTargets(targets, function (v) { return v > 0; }); - }; - c3_chart_internal_fn.isOrderDesc = function () { - var config = this.config; - return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'desc'; - }; - c3_chart_internal_fn.isOrderAsc = function () { - var config = this.config; - return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'asc'; - }; - c3_chart_internal_fn.orderTargets = function (targets) { - var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc(); - if (orderAsc || orderDesc) { - targets.sort(function (t1, t2) { - var reducer = function (p, c) { return p + Math.abs(c.value); }; - var t1Sum = t1.values.reduce(reducer, 0), - t2Sum = t2.values.reduce(reducer, 0); - return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum; - }); - } else if (isFunction(config.data_order)) { - targets.sort(config.data_order); - } // TODO: accept name array for order - return targets; - }; - c3_chart_internal_fn.filterByX = function (targets, x) { - return this.d3.merge(targets.map(function (t) { return t.values; })).filter(function (v) { return v.x - x === 0; }); - }; - c3_chart_internal_fn.filterRemoveNull = function (data) { - return data.filter(function (d) { return isValue(d.value); }); - }; - c3_chart_internal_fn.filterByXDomain = function (targets, xDomain) { - return targets.map(function (t) { - return { - id: t.id, - id_org: t.id_org, - values: t.values.filter(function (v) { - return xDomain[0] <= v.x && v.x <= xDomain[1]; - }) - }; - }); - }; - c3_chart_internal_fn.hasDataLabel = function () { - var config = this.config; - if (typeof config.data_labels === 'boolean' && config.data_labels) { - return true; - } else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) { - return true; - } - return false; - }; - c3_chart_internal_fn.getDataLabelLength = function (min, max, key) { - var $$ = this, - lengths = [0, 0], paddingCoef = 1.3; - $$.selectChart.select('svg').selectAll('.dummy') - .data([min, max]) - .enter().append('text') - .text(function (d) { return $$.dataLabelFormat(d.id)(d); }) - .each(function (d, i) { - lengths[i] = this.getBoundingClientRect()[key] * paddingCoef; - }) - .remove(); - return lengths; - }; - c3_chart_internal_fn.isNoneArc = function (d) { - return this.hasTarget(this.data.targets, d.id); - }, - c3_chart_internal_fn.isArc = function (d) { - return 'data' in d && this.hasTarget(this.data.targets, d.data.id); - }; - c3_chart_internal_fn.findSameXOfValues = function (values, index) { - var i, targetX = values[index].x, sames = []; - for (i = index - 1; i >= 0; i--) { - if (targetX !== values[i].x) { break; } - sames.push(values[i]); - } - for (i = index; i < values.length; i++) { - if (targetX !== values[i].x) { break; } - sames.push(values[i]); - } - return sames; - }; - - c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) { - var $$ = this, candidates; - - // map to array of closest points of each target - candidates = targets.map(function (target) { - return $$.findClosest(target.values, pos); - }); - - // decide closest point and return - return $$.findClosest(candidates, pos); - }; - c3_chart_internal_fn.findClosest = function (values, pos) { - var $$ = this, minDist = $$.config.point_sensitivity, closest; - - // find mouseovering bar - values.filter(function (v) { return v && $$.isBarType(v.id); }).forEach(function (v) { - var shape = $$.main.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node(); - if (!closest && $$.isWithinBar(shape)) { - closest = v; - } - }); - - // find closest point from non-bar - values.filter(function (v) { return v && !$$.isBarType(v.id); }).forEach(function (v) { - var d = $$.dist(v, pos); - if (d < minDist) { - minDist = d; - closest = v; - } - }); - - return closest; - }; - c3_chart_internal_fn.dist = function (data, pos) { - var $$ = this, config = $$.config, - xIndex = config.axis_rotated ? 1 : 0, - yIndex = config.axis_rotated ? 0 : 1, - y = $$.circleY(data, data.index), - x = $$.x(data.x); - return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2)); - }; - c3_chart_internal_fn.convertValuesToStep = function (values) { - var converted = [].concat(values), i; - - if (!this.isCategorized()) { - return values; - } - - for (i = values.length + 1; 0 < i; i--) { - converted[i] = converted[i - 1]; - } - - converted[0] = { - x: converted[0].x - 1, - value: converted[0].value, - id: converted[0].id - }; - converted[values.length + 1] = { - x: converted[values.length].x + 1, - value: converted[values.length].value, - id: converted[values.length].id - }; - - return converted; - }; - c3_chart_internal_fn.updateDataAttributes = function (name, attrs) { - var $$ = this, config = $$.config, current = config['data_' + name]; - if (typeof attrs === 'undefined') { return current; } - Object.keys(attrs).forEach(function (id) { - current[id] = attrs[id]; - }); - $$.redraw({withLegend: true}); - return current; - }; - - c3_chart_internal_fn.convertUrlToData = function (url, mimeType, headers, keys, done) { - var $$ = this, type = mimeType ? mimeType : 'csv'; - var req = $$.d3.xhr(url); - if (headers) { - Object.keys(headers).forEach(function (header) { - req.header(header, headers[header]); - }); - } - req.get(function (error, data) { - var d; - if (!data) { - throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')'); - } - if (type === 'json') { - d = $$.convertJsonToData(JSON.parse(data.response), keys); - } else if (type === 'tsv') { - d = $$.convertTsvToData(data.response); - } else { - d = $$.convertCsvToData(data.response); - } - done.call($$, d); - }); - }; - c3_chart_internal_fn.convertXsvToData = function (xsv, parser) { - var rows = parser.parseRows(xsv), d; - if (rows.length === 1) { - d = [{}]; - rows[0].forEach(function (id) { - d[0][id] = null; - }); - } else { - d = parser.parse(xsv); - } - return d; - }; - c3_chart_internal_fn.convertCsvToData = function (csv) { - return this.convertXsvToData(csv, this.d3.csv); - }; - c3_chart_internal_fn.convertTsvToData = function (tsv) { - return this.convertXsvToData(tsv, this.d3.tsv); - }; - c3_chart_internal_fn.convertJsonToData = function (json, keys) { - var $$ = this, - new_rows = [], targetKeys, data; - if (keys) { // when keys specified, json would be an array that includes objects - if (keys.x) { - targetKeys = keys.value.concat(keys.x); - $$.config.data_x = keys.x; - } else { - targetKeys = keys.value; - } - new_rows.push(targetKeys); - json.forEach(function (o) { - var new_row = []; - targetKeys.forEach(function (key) { - // convert undefined to null because undefined data will be removed in convertDataToTargets() - var v = $$.findValueInJson(o, key); - if (isUndefined(v)) { - v = null; - } - new_row.push(v); - }); - new_rows.push(new_row); - }); - data = $$.convertRowsToData(new_rows); - } else { - Object.keys(json).forEach(function (key) { - new_rows.push([key].concat(json[key])); - }); - data = $$.convertColumnsToData(new_rows); - } - return data; - }; - c3_chart_internal_fn.findValueInJson = function (object, path) { - path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .) - path = path.replace(/^\./, ''); // strip a leading dot - var pathArray = path.split('.'); - for (var i = 0; i < pathArray.length; ++i) { - var k = pathArray[i]; - if (k in object) { - object = object[k]; - } else { - return; - } - } - return object; - }; - c3_chart_internal_fn.convertRowsToData = function (rows) { - var keys = rows[0], new_row = {}, new_rows = [], i, j; - for (i = 1; i < rows.length; i++) { - new_row = {}; - for (j = 0; j < rows[i].length; j++) { - if (isUndefined(rows[i][j])) { - throw new Error("Source data is missing a component at (" + i + "," + j + ")!"); - } - new_row[keys[j]] = rows[i][j]; - } - new_rows.push(new_row); - } - return new_rows; - }; - c3_chart_internal_fn.convertColumnsToData = function (columns) { - var new_rows = [], i, j, key; - for (i = 0; i < columns.length; i++) { - key = columns[i][0]; - for (j = 1; j < columns[i].length; j++) { - if (isUndefined(new_rows[j - 1])) { - new_rows[j - 1] = {}; - } - if (isUndefined(columns[i][j])) { - throw new Error("Source data is missing a component at (" + i + "," + j + ")!"); - } - new_rows[j - 1][key] = columns[i][j]; - } - } - return new_rows; - }; - c3_chart_internal_fn.convertDataToTargets = function (data, appendXs) { - var $$ = this, config = $$.config, - ids = $$.d3.keys(data[0]).filter($$.isNotX, $$), - xs = $$.d3.keys(data[0]).filter($$.isX, $$), - targets; - - // save x for update data by load when custom x and c3.x API - ids.forEach(function (id) { - var xKey = $$.getXKey(id); - - if ($$.isCustomX() || $$.isTimeSeries()) { - // if included in input data - if (xs.indexOf(xKey) >= 0) { - $$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).concat( - data.map(function (d) { return d[xKey]; }) - .filter(isValue) - .map(function (rawX, i) { return $$.generateTargetX(rawX, id, i); }) - ); - } - // if not included in input data, find from preloaded data of other id's x - else if (config.data_x) { - $$.data.xs[id] = $$.getOtherTargetXs(); - } - // if not included in input data, find from preloaded data - else if (notEmpty(config.data_xs)) { - $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets); - } - // MEMO: if no x included, use same x of current will be used - } else { - $$.data.xs[id] = data.map(function (d, i) { return i; }); - } - }); - - - // check x is defined - ids.forEach(function (id) { - if (!$$.data.xs[id]) { - throw new Error('x is not defined for id = "' + id + '".'); - } - }); - - // convert to target - targets = ids.map(function (id, index) { - var convertedId = config.data_idConverter(id); - return { - id: convertedId, - id_org: id, - values: data.map(function (d, i) { - var xKey = $$.getXKey(id), rawX = d[xKey], - value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x; - // use x as categories if custom x and categorized - if ($$.isCustomX() && $$.isCategorized() && index === 0 && !isUndefined(rawX)) { - if (index === 0 && i === 0) { - config.axis_x_categories = []; - } - x = config.axis_x_categories.indexOf(rawX); - if (x === -1) { - x = config.axis_x_categories.length; - config.axis_x_categories.push(rawX); - } - } else { - x = $$.generateTargetX(rawX, id, i); - } - // mark as x = undefined if value is undefined and filter to remove after mapped - if (isUndefined(d[id]) || $$.data.xs[id].length <= i) { - x = undefined; - } - return {x: x, value: value, id: convertedId}; - }).filter(function (v) { return isDefined(v.x); }) - }; - }); - - // finish targets - targets.forEach(function (t) { - var i; - // sort values by its x - if (config.data_xSort) { - t.values = t.values.sort(function (v1, v2) { - var x1 = v1.x || v1.x === 0 ? v1.x : Infinity, - x2 = v2.x || v2.x === 0 ? v2.x : Infinity; - return x1 - x2; - }); - } - // indexing each value - i = 0; - t.values.forEach(function (v) { - v.index = i++; - }); - // this needs to be sorted because its index and value.index is identical - $$.data.xs[t.id].sort(function (v1, v2) { - return v1 - v2; - }); - }); - - // cache information about values - $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets); - $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets); - - // set target types - if (config.data_type) { - $$.setTargetType($$.mapToIds(targets).filter(function (id) { return ! (id in config.data_types); }), config.data_type); - } - - // cache as original id keyed - targets.forEach(function (d) { - $$.addCache(d.id_org, d); - }); - - return targets; - }; - - c3_chart_internal_fn.load = function (targets, args) { - var $$ = this; - if (targets) { - // filter loading targets if needed - if (args.filter) { - targets = targets.filter(args.filter); - } - // set type if args.types || args.type specified - if (args.type || args.types) { - targets.forEach(function (t) { - var type = args.types && args.types[t.id] ? args.types[t.id] : args.type; - $$.setTargetType(t.id, type); - }); - } - // Update/Add data - $$.data.targets.forEach(function (d) { - for (var i = 0; i < targets.length; i++) { - if (d.id === targets[i].id) { - d.values = targets[i].values; - targets.splice(i, 1); - break; - } - } - }); - $$.data.targets = $$.data.targets.concat(targets); // add remained - } - - // Set targets - $$.updateTargets($$.data.targets); - - // Redraw with new targets - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); - - if (args.done) { args.done(); } - }; - c3_chart_internal_fn.loadFromArgs = function (args) { - var $$ = this; - if (args.data) { - $$.load($$.convertDataToTargets(args.data), args); - } - else if (args.url) { - $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) { - $$.load($$.convertDataToTargets(data), args); - }); - } - else if (args.json) { - $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args); - } - else if (args.rows) { - $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args); - } - else if (args.columns) { - $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args); - } - else { - $$.load(null, args); - } - }; - c3_chart_internal_fn.unload = function (targetIds, done) { - var $$ = this; - if (!done) { - done = function () {}; - } - // filter existing target - targetIds = targetIds.filter(function (id) { return $$.hasTarget($$.data.targets, id); }); - // If no target, call done and return - if (!targetIds || targetIds.length === 0) { - done(); - return; - } - $$.svg.selectAll(targetIds.map(function (id) { return $$.selectorTarget(id); })) - .transition() - .style('opacity', 0) - .remove() - .call($$.endall, done); - targetIds.forEach(function (id) { - // Reset fadein for future load - $$.withoutFadeIn[id] = false; - // Remove target's elements - if ($$.legend) { - $$.legend.selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove(); - } - // Remove target - $$.data.targets = $$.data.targets.filter(function (t) { - return t.id !== id; - }); - }); - }; - - c3_chart_internal_fn.categoryName = function (i) { - var config = this.config; - return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i; - }; - - c3_chart_internal_fn.initEventRect = function () { - var $$ = this; - $$.main.select('.' + CLASS.chart).append("g") - .attr("class", CLASS.eventRects) - .style('fill-opacity', 0); - }; - c3_chart_internal_fn.redrawEventRect = function () { - var $$ = this, config = $$.config, - eventRectUpdate, maxDataCountTarget, - isMultipleX = $$.isMultipleX(); - - // rects for mouseover - var eventRects = $$.main.select('.' + CLASS.eventRects) - .style('cursor', config.zoom_enabled ? config.axis_rotated ? 'ns-resize' : 'ew-resize' : null) - .classed(CLASS.eventRectsMultiple, isMultipleX) - .classed(CLASS.eventRectsSingle, !isMultipleX); - - // clear old rects - eventRects.selectAll('.' + CLASS.eventRect).remove(); - - // open as public variable - $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect); - - if (isMultipleX) { - eventRectUpdate = $$.eventRect.data([0]); - // enter : only one rect will be added - $$.generateEventRectsForMultipleXs(eventRectUpdate.enter()); - // update - $$.updateEventRect(eventRectUpdate); - // exit : not needed because always only one rect exists - } - else { - // Set data and update $$.eventRect - maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets); - eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []); - $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect); - eventRectUpdate = $$.eventRect.data(function (d) { return d; }); - // enter - $$.generateEventRectsForSingleX(eventRectUpdate.enter()); - // update - $$.updateEventRect(eventRectUpdate); - // exit - eventRectUpdate.exit().remove(); - } - }; - c3_chart_internal_fn.updateEventRect = function (eventRectUpdate) { - var $$ = this, config = $$.config, - x, y, w, h, rectW, rectX; - - // set update selection if null - eventRectUpdate = eventRectUpdate || $$.eventRect.data(function (d) { return d; }); - - if ($$.isMultipleX()) { - // TODO: rotated not supported yet - x = 0; - y = 0; - w = $$.width; - h = $$.height; - } - else { - if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) { - - // update index for x that is used by prevX and nextX - $$.updateXs(); - - rectW = function (d) { - var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index); - - // if there this is a single data point make the eventRect full width (or height) - if (prevX === null && nextX === null) { - return config.axis_rotated ? $$.height : $$.width; - } - - if (prevX === null) { prevX = $$.x.domain()[0]; } - if (nextX === null) { nextX = $$.x.domain()[1]; } - - return Math.max(0, ($$.x(nextX) - $$.x(prevX)) / 2); - }; - rectX = function (d) { - var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), - thisX = $$.data.xs[d.id][d.index]; - - // if there this is a single data point position the eventRect at 0 - if (prevX === null && nextX === null) { - return 0; - } - - if (prevX === null) { prevX = $$.x.domain()[0]; } - - return ($$.x(thisX) + $$.x(prevX)) / 2; - }; - } else { - rectW = $$.getEventRectWidth(); - rectX = function (d) { - return $$.x(d.x) - (rectW / 2); - }; - } - x = config.axis_rotated ? 0 : rectX; - y = config.axis_rotated ? rectX : 0; - w = config.axis_rotated ? $$.width : rectW; - h = config.axis_rotated ? rectW : $$.height; - } - - eventRectUpdate - .attr('class', $$.classEvent.bind($$)) - .attr("x", x) - .attr("y", y) - .attr("width", w) - .attr("height", h); - }; - c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) { - var $$ = this, d3 = $$.d3, config = $$.config; - eventRectEnter.append("rect") - .attr("class", $$.classEvent.bind($$)) - .style("cursor", config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null) - .on('mouseover', function (d) { - var index = d.index; - - if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing - if ($$.hasArcType()) { return; } - - // Expand shapes for selection - if (config.point_focus_expand_enabled) { $$.expandCircles(index, null, true); } - $$.expandBars(index, null, true); - - // Call event handler - $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) { - config.data_onmouseover.call($$.api, d); - }); - }) - .on('mouseout', function (d) { - var index = d.index; - if (!$$.config) { return; } // chart is destroyed - if ($$.hasArcType()) { return; } - $$.hideXGridFocus(); - $$.hideTooltip(); - // Undo expanded shapes - $$.unexpandCircles(); - $$.unexpandBars(); - // Call event handler - $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) { - config.data_onmouseout.call($$.api, d); - }); - }) - .on('mousemove', function (d) { - var selectedData, index = d.index, - eventRect = $$.svg.select('.' + CLASS.eventRect + '-' + index); - - if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing - if ($$.hasArcType()) { return; } - - if ($$.isStepType(d) && $$.config.line_step_type === 'step-after' && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) { - index -= 1; - } - - // Show tooltip - selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) { - return $$.addName($$.getValueOnIndex(t.values, index)); - }); - - if (config.tooltip_grouped) { - $$.showTooltip(selectedData, this); - $$.showXGridFocus(selectedData); - } - - if (config.tooltip_grouped && (!config.data_selection_enabled || config.data_selection_grouped)) { - return; - } - - $$.main.selectAll('.' + CLASS.shape + '-' + index) - .each(function () { - d3.select(this).classed(CLASS.EXPANDED, true); - if (config.data_selection_enabled) { - eventRect.style('cursor', config.data_selection_grouped ? 'pointer' : null); - } - if (!config.tooltip_grouped) { - $$.hideXGridFocus(); - $$.hideTooltip(); - if (!config.data_selection_grouped) { - $$.unexpandCircles(index); - $$.unexpandBars(index); - } - } - }) - .filter(function (d) { - return $$.isWithinShape(this, d); - }) - .each(function (d) { - if (config.data_selection_enabled && (config.data_selection_grouped || config.data_selection_isselectable(d))) { - eventRect.style('cursor', 'pointer'); - } - if (!config.tooltip_grouped) { - $$.showTooltip([d], this); - $$.showXGridFocus([d]); - if (config.point_focus_expand_enabled) { $$.expandCircles(index, d.id, true); } - $$.expandBars(index, d.id, true); - } - }); - }) - .on('click', function (d) { - var index = d.index; - if ($$.hasArcType() || !$$.toggleShape) { return; } - if ($$.cancelClick) { - $$.cancelClick = false; - return; - } - if ($$.isStepType(d) && config.line_step_type === 'step-after' && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) { - index -= 1; - } - $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) { - if (config.data_selection_grouped || $$.isWithinShape(this, d)) { - $$.toggleShape(this, d, index); - $$.config.data_onclick.call($$.api, d, this); - } - }); - }) - .call( - config.data_selection_draggable && $$.drag ? ( - d3.behavior.drag().origin(Object) - .on('drag', function () { $$.drag(d3.mouse(this)); }) - .on('dragstart', function () { $$.dragstart(d3.mouse(this)); }) - .on('dragend', function () { $$.dragend(); }) - ) : function () {} - ); - }; - - c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter) { - var $$ = this, d3 = $$.d3, config = $$.config; - - function mouseout() { - $$.svg.select('.' + CLASS.eventRect).style('cursor', null); - $$.hideXGridFocus(); - $$.hideTooltip(); - $$.unexpandCircles(); - $$.unexpandBars(); - } - - eventRectEnter.append('rect') - .attr('x', 0) - .attr('y', 0) - .attr('width', $$.width) - .attr('height', $$.height) - .attr('class', CLASS.eventRect) - .on('mouseout', function () { - if (!$$.config) { return; } // chart is destroyed - if ($$.hasArcType()) { return; } - mouseout(); - }) - .on('mousemove', function () { - var targetsToShow = $$.filterTargetsToShow($$.data.targets); - var mouse, closest, sameXData, selectedData; - - if ($$.dragging) { return; } // do nothing when dragging - if ($$.hasArcType(targetsToShow)) { return; } - - mouse = d3.mouse(this); - closest = $$.findClosestFromTargets(targetsToShow, mouse); - - if ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) { - config.data_onmouseout.call($$.api, $$.mouseover); - $$.mouseover = undefined; - } - - if (! closest) { - mouseout(); - return; - } - - if ($$.isScatterType(closest) || !config.tooltip_grouped) { - sameXData = [closest]; - } else { - sameXData = $$.filterByX(targetsToShow, closest.x); - } - - // show tooltip when cursor is close to some point - selectedData = sameXData.map(function (d) { - return $$.addName(d); - }); - $$.showTooltip(selectedData, this); - - // expand points - if (config.point_focus_expand_enabled) { - $$.expandCircles(closest.index, closest.id, true); - } - $$.expandBars(closest.index, closest.id, true); - - // Show xgrid focus line - $$.showXGridFocus(selectedData); - - // Show cursor as pointer if point is close to mouse position - if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) { - $$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer'); - if (!$$.mouseover) { - config.data_onmouseover.call($$.api, closest); - $$.mouseover = closest; - } - } - }) - .on('click', function () { - var targetsToShow = $$.filterTargetsToShow($$.data.targets); - var mouse, closest; - if ($$.hasArcType(targetsToShow)) { return; } - - mouse = d3.mouse(this); - closest = $$.findClosestFromTargets(targetsToShow, mouse); - if (! closest) { return; } - // select if selection enabled - if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) { - $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)).selectAll('.' + CLASS.shape + '-' + closest.index).each(function () { - if (config.data_selection_grouped || $$.isWithinShape(this, closest)) { - $$.toggleShape(this, closest, closest.index); - $$.config.data_onclick.call($$.api, closest, this); - } - }); - } - }) - .call( - config.data_selection_draggable && $$.drag ? ( - d3.behavior.drag().origin(Object) - .on('drag', function () { $$.drag(d3.mouse(this)); }) - .on('dragstart', function () { $$.dragstart(d3.mouse(this)); }) - .on('dragend', function () { $$.dragend(); }) - ) : function () {} - ); - }; - c3_chart_internal_fn.dispatchEvent = function (type, index, mouse) { - var $$ = this, - selector = '.' + CLASS.eventRect + (!$$.isMultipleX() ? '-' + index : ''), - eventRect = $$.main.select(selector).node(), - box = eventRect.getBoundingClientRect(), - x = box.left + (mouse ? mouse[0] : 0), - y = box.top + (mouse ? mouse[1] : 0), - event = document.createEvent("MouseEvents"); - - event.initMouseEvent(type, true, true, window, 0, x, y, x, y, - false, false, false, false, 0, null); - eventRect.dispatchEvent(event); - }; - - c3_chart_internal_fn.getCurrentWidth = function () { - var $$ = this, config = $$.config; - return config.size_width ? config.size_width : $$.getParentWidth(); - }; - c3_chart_internal_fn.getCurrentHeight = function () { - var $$ = this, config = $$.config, - h = config.size_height ? config.size_height : $$.getParentHeight(); - return h > 0 ? h : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1); - }; - c3_chart_internal_fn.getCurrentPaddingTop = function () { - var $$ = this, - config = $$.config, - padding = isValue(config.padding_top) ? config.padding_top : 0; - if ($$.title && $$.title.node()) { - padding += $$.getTitlePadding(); - } - return padding; - }; - c3_chart_internal_fn.getCurrentPaddingBottom = function () { - var config = this.config; - return isValue(config.padding_bottom) ? config.padding_bottom : 0; - }; - c3_chart_internal_fn.getCurrentPaddingLeft = function (withoutRecompute) { - var $$ = this, config = $$.config; - if (isValue(config.padding_left)) { - return config.padding_left; - } else if (config.axis_rotated) { - return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40); - } else if (!config.axis_y_show || config.axis_y_inner) { // && !config.axis_rotated - return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1; - } else { - return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute)); - } - }; - c3_chart_internal_fn.getCurrentPaddingRight = function () { - var $$ = this, config = $$.config, - defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0; - if (isValue(config.padding_right)) { - return config.padding_right + 1; // 1 is needed not to hide tick line - } else if (config.axis_rotated) { - return defaultPadding + legendWidthOnRight; - } else if (!config.axis_y2_show || config.axis_y2_inner) { // && !config.axis_rotated - return 2 + legendWidthOnRight + ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0); - } else { - return ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight; - } - }; - - c3_chart_internal_fn.getParentRectValue = function (key) { - var parent = this.selectChart.node(), v; - while (parent && parent.tagName !== 'BODY') { - try { - v = parent.getBoundingClientRect()[key]; - } catch(e) { - if (key === 'width') { - // In IE in certain cases getBoundingClientRect - // will cause an "unspecified error" - v = parent.offsetWidth; - } - } - if (v) { - break; - } - parent = parent.parentNode; - } - return v; - }; - c3_chart_internal_fn.getParentWidth = function () { - return this.getParentRectValue('width'); - }; - c3_chart_internal_fn.getParentHeight = function () { - var h = this.selectChart.style('height'); - return h.indexOf('px') > 0 ? +h.replace('px', '') : 0; - }; - - - c3_chart_internal_fn.getSvgLeft = function (withoutRecompute) { - var $$ = this, config = $$.config, - hasLeftAxisRect = config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner), - leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY, - leftAxis = $$.main.select('.' + leftAxisClass).node(), - svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : {right: 0}, - chartRect = $$.selectChart.node().getBoundingClientRect(), - hasArc = $$.hasArcType(), - svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute)); - return svgLeft > 0 ? svgLeft : 0; - }; - - - c3_chart_internal_fn.getAxisWidthByAxisId = function (id, withoutRecompute) { - var $$ = this, position = $$.axis.getLabelPositionById(id); - return $$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40); - }; - c3_chart_internal_fn.getHorizontalAxisHeight = function (axisId) { - var $$ = this, config = $$.config, h = 30; - if (axisId === 'x' && !config.axis_x_show) { return 8; } - if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; } - if (axisId === 'y' && !config.axis_y_show) { - return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1; - } - if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; } - // Calculate x axis height when tick rotated - if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) { - h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180); - } - // Calculate y axis height when tick rotated - if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) { - h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_y_tick_rotate) / 180); - } - return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0); - }; - - c3_chart_internal_fn.getEventRectWidth = function () { - return Math.max(0, this.xAxis.tickInterval()); - }; - - c3_chart_internal_fn.getShapeIndices = function (typeFilter) { - var $$ = this, config = $$.config, - indices = {}, i = 0, j, k; - $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) { - for (j = 0; j < config.data_groups.length; j++) { - if (config.data_groups[j].indexOf(d.id) < 0) { continue; } - for (k = 0; k < config.data_groups[j].length; k++) { - if (config.data_groups[j][k] in indices) { - indices[d.id] = indices[config.data_groups[j][k]]; - break; - } - } - } - if (isUndefined(indices[d.id])) { indices[d.id] = i++; } - }); - indices.__max__ = i - 1; - return indices; - }; - c3_chart_internal_fn.getShapeX = function (offset, targetsNum, indices, isSub) { - var $$ = this, scale = isSub ? $$.subX : $$.x; - return function (d) { - var index = d.id in indices ? indices[d.id] : 0; - return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0; - }; - }; - c3_chart_internal_fn.getShapeY = function (isSub) { - var $$ = this; - return function (d) { - var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id); - return scale(d.value); - }; - }; - c3_chart_internal_fn.getShapeOffset = function (typeFilter, indices, isSub) { - var $$ = this, - targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))), - targetIds = targets.map(function (t) { return t.id; }); - return function (d, i) { - var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id), - y0 = scale(0), offset = y0; - targets.forEach(function (t) { - var values = $$.isStepType(d) ? $$.convertValuesToStep(t.values) : t.values; - if (t.id === d.id || indices[t.id] !== indices[d.id]) { return; } - if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) { - // check if the x values line up - if (typeof values[i] === 'undefined' || +values[i].x !== +d.x) { // "+" for timeseries - // if not, try to find the value that does line up - i = -1; - values.forEach(function (v, j) { - if (v.x === d.x) { - i = j; - } - }); - } - if (i in values && values[i].value * d.value >= 0) { - offset += scale(values[i].value) - y0; - } - } - }); - return offset; - }; - }; - c3_chart_internal_fn.isWithinShape = function (that, d) { - var $$ = this, - shape = $$.d3.select(that), isWithin; - if (!$$.isTargetToShow(d.id)) { - isWithin = false; - } - else if (that.nodeName === 'circle') { - isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value)) : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5); - } - else if (that.nodeName === 'path') { - isWithin = shape.classed(CLASS.bar) ? $$.isWithinBar(that) : true; - } - return isWithin; - }; - - - c3_chart_internal_fn.getInterpolate = function (d) { - var $$ = this, - interpolation = $$.isInterpolationType($$.config.spline_interpolation_type) ? $$.config.spline_interpolation_type : 'cardinal'; - return $$.isSplineType(d) ? interpolation : $$.isStepType(d) ? $$.config.line_step_type : "linear"; - }; - - c3_chart_internal_fn.initLine = function () { - var $$ = this; - $$.main.select('.' + CLASS.chart).append("g") - .attr("class", CLASS.chartLines); - }; - c3_chart_internal_fn.updateTargetsForLine = function (targets) { - var $$ = this, config = $$.config, - mainLineUpdate, mainLineEnter, - classChartLine = $$.classChartLine.bind($$), - classLines = $$.classLines.bind($$), - classAreas = $$.classAreas.bind($$), - classCircles = $$.classCircles.bind($$), - classFocus = $$.classFocus.bind($$); - mainLineUpdate = $$.main.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine) - .data(targets) - .attr('class', function (d) { return classChartLine(d) + classFocus(d); }); - mainLineEnter = mainLineUpdate.enter().append('g') - .attr('class', classChartLine) - .style('opacity', 0) - .style("pointer-events", "none"); - // Lines for each data - mainLineEnter.append('g') - .attr("class", classLines); - // Areas - mainLineEnter.append('g') - .attr('class', classAreas); - // Circles for each data point on lines - mainLineEnter.append('g') - .attr("class", function (d) { return $$.generateClass(CLASS.selectedCircles, d.id); }); - mainLineEnter.append('g') - .attr("class", classCircles) - .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; }); - // Update date for selected circles - targets.forEach(function (t) { - $$.main.selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll('.' + CLASS.selectedCircle).each(function (d) { - d.value = t.values[d.index].value; - }); - }); - // MEMO: can not keep same color... - //mainLineUpdate.exit().remove(); - }; - c3_chart_internal_fn.updateLine = function (durationForExit) { - var $$ = this; - $$.mainLine = $$.main.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line) - .data($$.lineData.bind($$)); - $$.mainLine.enter().append('path') - .attr('class', $$.classLine.bind($$)) - .style("stroke", $$.color); - $$.mainLine - .style("opacity", $$.initialOpacity.bind($$)) - .style('shape-rendering', function (d) { return $$.isStepType(d) ? 'crispEdges' : ''; }) - .attr('transform', null); - $$.mainLine.exit().transition().duration(durationForExit) - .style('opacity', 0) - .remove(); - }; - c3_chart_internal_fn.redrawLine = function (drawLine, withTransition) { - return [ - (withTransition ? this.mainLine.transition(Math.random().toString()) : this.mainLine) - .attr("d", drawLine) - .style("stroke", this.color) - .style("opacity", 1) - ]; - }; - c3_chart_internal_fn.generateDrawLine = function (lineIndices, isSub) { - var $$ = this, config = $$.config, - line = $$.d3.svg.line(), - getPoints = $$.generateGetLinePoints(lineIndices, isSub), - yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, - xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); }, - yValue = function (d, i) { - return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value); - }; - - line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue); - if (!config.line_connectNull) { line = line.defined(function (d) { return d.value != null; }); } - return function (d) { - var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values, - x = isSub ? $$.x : $$.subX, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path; - if ($$.isLineType(d)) { - if (config.data_regions[d.id]) { - path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]); - } else { - if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); } - path = line.interpolate($$.getInterpolate(d))(values); - } - } else { - if (values[0]) { - x0 = x(values[0].x); - y0 = y(values[0].value); - } - path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0; - } - return path ? path : "M 0 0"; - }; - }; - c3_chart_internal_fn.generateGetLinePoints = function (lineIndices, isSub) { // partial duplication of generateGetBarPoints - var $$ = this, config = $$.config, - lineTargetsNum = lineIndices.__max__ + 1, - x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub), - y = $$.getShapeY(!!isSub), - lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub), - yScale = isSub ? $$.getSubYScale : $$.getYScale; - return function (d, i) { - var y0 = yScale.call($$, d.id)(0), - offset = lineOffset(d, i) || y0, // offset is for stacked area chart - posX = x(d), posY = y(d); - // fix posY not to overflow opposite quadrant - if (config.axis_rotated) { - if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; } - } - // 1 point that marks the line position - return [ - [posX, posY - (y0 - offset)], - [posX, posY - (y0 - offset)], // needed for compatibility - [posX, posY - (y0 - offset)], // needed for compatibility - [posX, posY - (y0 - offset)] // needed for compatibility - ]; - }; - }; - - - c3_chart_internal_fn.lineWithRegions = function (d, x, y, _regions) { - var $$ = this, config = $$.config, - prev = -1, i, j, - s = "M", sWithRegion, - xp, yp, dx, dy, dd, diff, diffx2, - xOffset = $$.isCategorized() ? 0.5 : 0, - xValue, yValue, - regions = []; - - function isWithinRegions(x, regions) { - var i; - for (i = 0; i < regions.length; i++) { - if (regions[i].start < x && x <= regions[i].end) { return true; } - } - return false; - } - - // Check start/end of regions - if (isDefined(_regions)) { - for (i = 0; i < _regions.length; i++) { - regions[i] = {}; - if (isUndefined(_regions[i].start)) { - regions[i].start = d[0].x; - } else { - regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start; - } - if (isUndefined(_regions[i].end)) { - regions[i].end = d[d.length - 1].x; - } else { - regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end; - } - } - } - - // Set scales - xValue = config.axis_rotated ? function (d) { return y(d.value); } : function (d) { return x(d.x); }; - yValue = config.axis_rotated ? function (d) { return x(d.x); } : function (d) { return y(d.value); }; - - // Define svg generator function for region - function generateM(points) { - return 'M' + points[0][0] + ' ' + points[0][1] + ' ' + points[1][0] + ' ' + points[1][1]; - } - if ($$.isTimeSeries()) { - sWithRegion = function (d0, d1, j, diff) { - var x0 = d0.x.getTime(), x_diff = d1.x - d0.x, - xv0 = new Date(x0 + x_diff * j), - xv1 = new Date(x0 + x_diff * (j + diff)), - points; - if (config.axis_rotated) { - points = [[y(yp(j)), x(xv0)], [y(yp(j + diff)), x(xv1)]]; - } else { - points = [[x(xv0), y(yp(j))], [x(xv1), y(yp(j + diff))]]; - } - return generateM(points); - }; - } else { - sWithRegion = function (d0, d1, j, diff) { - var points; - if (config.axis_rotated) { - points = [[y(yp(j), true), x(xp(j))], [y(yp(j + diff), true), x(xp(j + diff))]]; - } else { - points = [[x(xp(j), true), y(yp(j))], [x(xp(j + diff), true), y(yp(j + diff))]]; - } - return generateM(points); - }; - } - - // Generate - for (i = 0; i < d.length; i++) { - - // Draw as normal - if (isUndefined(regions) || ! isWithinRegions(d[i].x, regions)) { - s += " " + xValue(d[i]) + " " + yValue(d[i]); - } - // Draw with region // TODO: Fix for horizotal charts - else { - xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries()); - yp = $$.getScale(d[i - 1].value, d[i].value); - - dx = x(d[i].x) - x(d[i - 1].x); - dy = y(d[i].value) - y(d[i - 1].value); - dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); - diff = 2 / dd; - diffx2 = diff * 2; - - for (j = diff; j <= 1; j += diffx2) { - s += sWithRegion(d[i - 1], d[i], j, diff); - } - } - prev = d[i].x; - } - - return s; - }; - - - c3_chart_internal_fn.updateArea = function (durationForExit) { - var $$ = this, d3 = $$.d3; - $$.mainArea = $$.main.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area) - .data($$.lineData.bind($$)); - $$.mainArea.enter().append('path') - .attr("class", $$.classArea.bind($$)) - .style("fill", $$.color) - .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; }); - $$.mainArea - .style("opacity", $$.orgAreaOpacity); - $$.mainArea.exit().transition().duration(durationForExit) - .style('opacity', 0) - .remove(); - }; - c3_chart_internal_fn.redrawArea = function (drawArea, withTransition) { - return [ - (withTransition ? this.mainArea.transition(Math.random().toString()) : this.mainArea) - .attr("d", drawArea) - .style("fill", this.color) - .style("opacity", this.orgAreaOpacity) - ]; - }; - c3_chart_internal_fn.generateDrawArea = function (areaIndices, isSub) { - var $$ = this, config = $$.config, area = $$.d3.svg.area(), - getPoints = $$.generateGetAreaPoints(areaIndices, isSub), - yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, - xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); }, - value0 = function (d, i) { - return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id)); - }, - value1 = function (d, i) { - return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value); - }; - - area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(config.area_above ? 0 : value0).y1(value1); - if (!config.line_connectNull) { - area = area.defined(function (d) { return d.value !== null; }); - } - - return function (d) { - var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values, - x0 = 0, y0 = 0, path; - if ($$.isAreaType(d)) { - if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); } - path = area.interpolate($$.getInterpolate(d))(values); - } else { - if (values[0]) { - x0 = $$.x(values[0].x); - y0 = $$.getYScale(d.id)(values[0].value); - } - path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0; - } - return path ? path : "M 0 0"; - }; - }; - c3_chart_internal_fn.getAreaBaseValue = function () { - return 0; - }; - c3_chart_internal_fn.generateGetAreaPoints = function (areaIndices, isSub) { // partial duplication of generateGetBarPoints - var $$ = this, config = $$.config, - areaTargetsNum = areaIndices.__max__ + 1, - x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub), - y = $$.getShapeY(!!isSub), - areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub), - yScale = isSub ? $$.getSubYScale : $$.getYScale; - return function (d, i) { - var y0 = yScale.call($$, d.id)(0), - offset = areaOffset(d, i) || y0, // offset is for stacked area chart - posX = x(d), posY = y(d); - // fix posY not to overflow opposite quadrant - if (config.axis_rotated) { - if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; } - } - // 1 point that marks the area position - return [ - [posX, offset], - [posX, posY - (y0 - offset)], - [posX, posY - (y0 - offset)], // needed for compatibility - [posX, offset] // needed for compatibility - ]; - }; - }; - - - c3_chart_internal_fn.updateCircle = function () { - var $$ = this; - $$.mainCircle = $$.main.selectAll('.' + CLASS.circles).selectAll('.' + CLASS.circle) - .data($$.lineOrScatterData.bind($$)); - $$.mainCircle.enter().append("circle") - .attr("class", $$.classCircle.bind($$)) - .attr("r", $$.pointR.bind($$)) - .style("fill", $$.color); - $$.mainCircle - .style("opacity", $$.initialOpacityForCircle.bind($$)); - $$.mainCircle.exit().remove(); - }; - c3_chart_internal_fn.redrawCircle = function (cx, cy, withTransition) { - var selectedCircles = this.main.selectAll('.' + CLASS.selectedCircle); - return [ - (withTransition ? this.mainCircle.transition(Math.random().toString()) : this.mainCircle) - .style('opacity', this.opacityForCircle.bind(this)) - .style("fill", this.color) - .attr("cx", cx) - .attr("cy", cy), - (withTransition ? selectedCircles.transition(Math.random().toString()) : selectedCircles) - .attr("cx", cx) - .attr("cy", cy) - ]; - }; - c3_chart_internal_fn.circleX = function (d) { - return d.x || d.x === 0 ? this.x(d.x) : null; - }; - c3_chart_internal_fn.updateCircleY = function () { - var $$ = this, lineIndices, getPoints; - if ($$.config.data_groups.length > 0) { - lineIndices = $$.getShapeIndices($$.isLineType), - getPoints = $$.generateGetLinePoints(lineIndices); - $$.circleY = function (d, i) { - return getPoints(d, i)[0][1]; - }; - } else { - $$.circleY = function (d) { - return $$.getYScale(d.id)(d.value); - }; - } - }; - c3_chart_internal_fn.getCircles = function (i, id) { - var $$ = this; - return (id ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : '')); - }; - c3_chart_internal_fn.expandCircles = function (i, id, reset) { - var $$ = this, - r = $$.pointExpandedR.bind($$); - if (reset) { $$.unexpandCircles(); } - $$.getCircles(i, id) - .classed(CLASS.EXPANDED, true) - .attr('r', r); - }; - c3_chart_internal_fn.unexpandCircles = function (i) { - var $$ = this, - r = $$.pointR.bind($$); - $$.getCircles(i) - .filter(function () { return $$.d3.select(this).classed(CLASS.EXPANDED); }) - .classed(CLASS.EXPANDED, false) - .attr('r', r); - }; - c3_chart_internal_fn.pointR = function (d) { - var $$ = this, config = $$.config; - return $$.isStepType(d) ? 0 : (isFunction(config.point_r) ? config.point_r(d) : config.point_r); - }; - c3_chart_internal_fn.pointExpandedR = function (d) { - var $$ = this, config = $$.config; - return config.point_focus_expand_enabled ? (config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75) : $$.pointR(d); - }; - c3_chart_internal_fn.pointSelectR = function (d) { - var $$ = this, config = $$.config; - return isFunction(config.point_select_r) ? config.point_select_r(d) : ((config.point_select_r) ? config.point_select_r : $$.pointR(d) * 4); - }; - c3_chart_internal_fn.isWithinCircle = function (that, r) { - var d3 = this.d3, - mouse = d3.mouse(that), d3_this = d3.select(that), - cx = +d3_this.attr("cx"), cy = +d3_this.attr("cy"); - return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r; - }; - c3_chart_internal_fn.isWithinStep = function (that, y) { - return Math.abs(y - this.d3.mouse(that)[1]) < 30; - }; - - c3_chart_internal_fn.initBar = function () { - var $$ = this; - $$.main.select('.' + CLASS.chart).append("g") - .attr("class", CLASS.chartBars); - }; - c3_chart_internal_fn.updateTargetsForBar = function (targets) { - var $$ = this, config = $$.config, - mainBarUpdate, mainBarEnter, - classChartBar = $$.classChartBar.bind($$), - classBars = $$.classBars.bind($$), - classFocus = $$.classFocus.bind($$); - mainBarUpdate = $$.main.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar) - .data(targets) - .attr('class', function (d) { return classChartBar(d) + classFocus(d); }); - mainBarEnter = mainBarUpdate.enter().append('g') - .attr('class', classChartBar) - .style('opacity', 0) - .style("pointer-events", "none"); - // Bars for each data - mainBarEnter.append('g') - .attr("class", classBars) - .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; }); - - }; - c3_chart_internal_fn.updateBar = function (durationForExit) { - var $$ = this, - barData = $$.barData.bind($$), - classBar = $$.classBar.bind($$), - initialOpacity = $$.initialOpacity.bind($$), - color = function (d) { return $$.color(d.id); }; - $$.mainBar = $$.main.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar) - .data(barData); - $$.mainBar.enter().append('path') - .attr("class", classBar) - .style("stroke", color) - .style("fill", color); - $$.mainBar - .style("opacity", initialOpacity); - $$.mainBar.exit().transition().duration(durationForExit) - .style('opacity', 0) - .remove(); - }; - c3_chart_internal_fn.redrawBar = function (drawBar, withTransition) { - return [ - (withTransition ? this.mainBar.transition(Math.random().toString()) : this.mainBar) - .attr('d', drawBar) - .style("fill", this.color) - .style("opacity", 1) - ]; - }; - c3_chart_internal_fn.getBarW = function (axis, barTargetsNum) { - var $$ = this, config = $$.config, - w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum : 0; - return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w; - }; - c3_chart_internal_fn.getBars = function (i, id) { - var $$ = this; - return (id ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : '')); - }; - c3_chart_internal_fn.expandBars = function (i, id, reset) { - var $$ = this; - if (reset) { $$.unexpandBars(); } - $$.getBars(i, id).classed(CLASS.EXPANDED, true); - }; - c3_chart_internal_fn.unexpandBars = function (i) { - var $$ = this; - $$.getBars(i).classed(CLASS.EXPANDED, false); - }; - c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) { - var $$ = this, config = $$.config, - getPoints = $$.generateGetBarPoints(barIndices, isSub); - return function (d, i) { - // 4 points that make a bar - var points = getPoints(d, i); - - // switch points if axis is rotated, not applicable for sub chart - var indexX = config.axis_rotated ? 1 : 0; - var indexY = config.axis_rotated ? 0 : 1; - - var path = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' + - 'L' + points[1][indexX] + ',' + points[1][indexY] + ' ' + - 'L' + points[2][indexX] + ',' + points[2][indexY] + ' ' + - 'L' + points[3][indexX] + ',' + points[3][indexY] + ' ' + - 'z'; - - return path; - }; - }; - c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) { - var $$ = this, - axis = isSub ? $$.subXAxis : $$.xAxis, - barTargetsNum = barIndices.__max__ + 1, - barW = $$.getBarW(axis, barTargetsNum), - barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub), - barY = $$.getShapeY(!!isSub), - barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub), - yScale = isSub ? $$.getSubYScale : $$.getYScale; - return function (d, i) { - var y0 = yScale.call($$, d.id)(0), - offset = barOffset(d, i) || y0, // offset is for stacked bar chart - posX = barX(d), posY = barY(d); - // fix posY not to overflow opposite quadrant - if ($$.config.axis_rotated) { - if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; } - } - // 4 points that make a bar - return [ - [posX, offset], - [posX, posY - (y0 - offset)], - [posX + barW, posY - (y0 - offset)], - [posX + barW, offset] - ]; - }; - }; - c3_chart_internal_fn.isWithinBar = function (that) { - var mouse = this.d3.mouse(that), box = that.getBoundingClientRect(), - seg0 = that.pathSegList.getItem(0), seg1 = that.pathSegList.getItem(1), - x = Math.min(seg0.x, seg1.x), y = Math.min(seg0.y, seg1.y), - w = box.width, h = box.height, offset = 2, - sx = x - offset, ex = x + w + offset, sy = y + h + offset, ey = y - offset; - return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy; - }; - - c3_chart_internal_fn.initText = function () { - var $$ = this; - $$.main.select('.' + CLASS.chart).append("g") - .attr("class", CLASS.chartTexts); - $$.mainText = $$.d3.selectAll([]); - }; - c3_chart_internal_fn.updateTargetsForText = function (targets) { - var $$ = this, mainTextUpdate, mainTextEnter, - classChartText = $$.classChartText.bind($$), - classTexts = $$.classTexts.bind($$), - classFocus = $$.classFocus.bind($$); - mainTextUpdate = $$.main.select('.' + CLASS.chartTexts).selectAll('.' + CLASS.chartText) - .data(targets) - .attr('class', function (d) { return classChartText(d) + classFocus(d); }); - mainTextEnter = mainTextUpdate.enter().append('g') - .attr('class', classChartText) - .style('opacity', 0) - .style("pointer-events", "none"); - mainTextEnter.append('g') - .attr('class', classTexts); - }; - c3_chart_internal_fn.updateText = function (durationForExit) { - var $$ = this, config = $$.config, - barOrLineData = $$.barOrLineData.bind($$), - classText = $$.classText.bind($$); - $$.mainText = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text) - .data(barOrLineData); - $$.mainText.enter().append('text') - .attr("class", classText) - .attr('text-anchor', function (d) { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; }) - .style("stroke", 'none') - .style("fill", function (d) { return $$.color(d); }) - .style("fill-opacity", 0); - $$.mainText - .text(function (d, i, j) { return $$.dataLabelFormat(d.id)(d.value, d.id, i, j); }); - $$.mainText.exit() - .transition().duration(durationForExit) - .style('fill-opacity', 0) - .remove(); - }; - c3_chart_internal_fn.redrawText = function (xForText, yForText, forFlow, withTransition) { - return [ - (withTransition ? this.mainText.transition() : this.mainText) - .attr('x', xForText) - .attr('y', yForText) - .style("fill", this.color) - .style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this)) - ]; - }; - c3_chart_internal_fn.getTextRect = function (text, cls, element) { - var dummy = this.d3.select('body').append('div').classed('c3', true), - svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0), - font = this.d3.select(element).style('font'), - rect; - svg.selectAll('.dummy') - .data([text]) - .enter().append('text') - .classed(cls ? cls : "", true) - .style('font', font) - .text(text) - .each(function () { rect = this.getBoundingClientRect(); }); - dummy.remove(); - return rect; - }; - c3_chart_internal_fn.generateXYForText = function (areaIndices, barIndices, lineIndices, forX) { - var $$ = this, - getAreaPoints = $$.generateGetAreaPoints(areaIndices, false), - getBarPoints = $$.generateGetBarPoints(barIndices, false), - getLinePoints = $$.generateGetLinePoints(lineIndices, false), - getter = forX ? $$.getXForText : $$.getYForText; - return function (d, i) { - var getPoints = $$.isAreaType(d) ? getAreaPoints : $$.isBarType(d) ? getBarPoints : getLinePoints; - return getter.call($$, getPoints(d, i), d, this); - }; - }; - c3_chart_internal_fn.getXForText = function (points, d, textElement) { - var $$ = this, - box = textElement.getBoundingClientRect(), xPos, padding; - if ($$.config.axis_rotated) { - padding = $$.isBarType(d) ? 4 : 6; - xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1); - } else { - xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0]; - } - // show labels regardless of the domain if value is null - if (d.value === null) { - if (xPos > $$.width) { - xPos = $$.width - box.width; - } else if (xPos < 0) { - xPos = 4; - } - } - return xPos; - }; - c3_chart_internal_fn.getYForText = function (points, d, textElement) { - var $$ = this, - box = textElement.getBoundingClientRect(), - yPos; - if ($$.config.axis_rotated) { - yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2; - } else { - yPos = points[2][1]; - if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) { - yPos += box.height; - if ($$.isBarType(d) && $$.isSafari()) { - yPos -= 3; - } - else if (!$$.isBarType(d) && $$.isChrome()) { - yPos += 3; - } - } else { - yPos += $$.isBarType(d) ? -3 : -6; - } - } - // show labels regardless of the domain if value is null - if (d.value === null && !$$.config.axis_rotated) { - if (yPos < box.height) { - yPos = box.height; - } else if (yPos > this.height) { - yPos = this.height - 4; - } - } - return yPos; - }; - - c3_chart_internal_fn.setTargetType = function (targetIds, type) { - var $$ = this, config = $$.config; - $$.mapToTargetIds(targetIds).forEach(function (id) { - $$.withoutFadeIn[id] = (type === config.data_types[id]); - config.data_types[id] = type; - }); - if (!targetIds) { - config.data_type = type; - } - }; - c3_chart_internal_fn.hasType = function (type, targets) { - var $$ = this, types = $$.config.data_types, has = false; - targets = targets || $$.data.targets; - if (targets && targets.length) { - targets.forEach(function (target) { - var t = types[target.id]; - if ((t && t.indexOf(type) >= 0) || (!t && type === 'line')) { - has = true; - } - }); - } else if (Object.keys(types).length) { - Object.keys(types).forEach(function (id) { - if (types[id] === type) { has = true; } - }); - } else { - has = $$.config.data_type === type; - } - return has; - }; - c3_chart_internal_fn.hasArcType = function (targets) { - return this.hasType('pie', targets) || this.hasType('donut', targets) || this.hasType('gauge', targets); - }; - c3_chart_internal_fn.isLineType = function (d) { - var config = this.config, id = isString(d) ? d : d.id; - return !config.data_types[id] || ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0; - }; - c3_chart_internal_fn.isStepType = function (d) { - var id = isString(d) ? d : d.id; - return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0; - }; - c3_chart_internal_fn.isSplineType = function (d) { - var id = isString(d) ? d : d.id; - return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0; - }; - c3_chart_internal_fn.isAreaType = function (d) { - var id = isString(d) ? d : d.id; - return ['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >= 0; - }; - c3_chart_internal_fn.isBarType = function (d) { - var id = isString(d) ? d : d.id; - return this.config.data_types[id] === 'bar'; - }; - c3_chart_internal_fn.isScatterType = function (d) { - var id = isString(d) ? d : d.id; - return this.config.data_types[id] === 'scatter'; - }; - c3_chart_internal_fn.isPieType = function (d) { - var id = isString(d) ? d : d.id; - return this.config.data_types[id] === 'pie'; - }; - c3_chart_internal_fn.isGaugeType = function (d) { - var id = isString(d) ? d : d.id; - return this.config.data_types[id] === 'gauge'; - }; - c3_chart_internal_fn.isDonutType = function (d) { - var id = isString(d) ? d : d.id; - return this.config.data_types[id] === 'donut'; - }; - c3_chart_internal_fn.isArcType = function (d) { - return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d); - }; - c3_chart_internal_fn.lineData = function (d) { - return this.isLineType(d) ? [d] : []; - }; - c3_chart_internal_fn.arcData = function (d) { - return this.isArcType(d.data) ? [d] : []; - }; - /* not used - function scatterData(d) { - return isScatterType(d) ? d.values : []; - } - */ - c3_chart_internal_fn.barData = function (d) { - return this.isBarType(d) ? d.values : []; - }; - c3_chart_internal_fn.lineOrScatterData = function (d) { - return this.isLineType(d) || this.isScatterType(d) ? d.values : []; - }; - c3_chart_internal_fn.barOrLineData = function (d) { - return this.isBarType(d) || this.isLineType(d) ? d.values : []; - }; - c3_chart_internal_fn.isInterpolationType = function (type) { - return ['linear', 'linear-closed', 'basis', 'basis-open', 'basis-closed', 'bundle', 'cardinal', 'cardinal-open', 'cardinal-closed', 'monotone'].indexOf(type) >= 0; - }; - - c3_chart_internal_fn.initGrid = function () { - var $$ = this, config = $$.config, d3 = $$.d3; - $$.grid = $$.main.append('g') - .attr("clip-path", $$.clipPathForGrid) - .attr('class', CLASS.grid); - if (config.grid_x_show) { - $$.grid.append("g").attr("class", CLASS.xgrids); - } - if (config.grid_y_show) { - $$.grid.append('g').attr('class', CLASS.ygrids); - } - if (config.grid_focus_show) { - $$.grid.append('g') - .attr("class", CLASS.xgridFocus) - .append('line') - .attr('class', CLASS.xgridFocus); - } - $$.xgrid = d3.selectAll([]); - if (!config.grid_lines_front) { $$.initGridLines(); } - }; - c3_chart_internal_fn.initGridLines = function () { - var $$ = this, d3 = $$.d3; - $$.gridLines = $$.main.append('g') - .attr("clip-path", $$.clipPathForGrid) - .attr('class', CLASS.grid + ' ' + CLASS.gridLines); - $$.gridLines.append('g').attr("class", CLASS.xgridLines); - $$.gridLines.append('g').attr('class', CLASS.ygridLines); - $$.xgridLines = d3.selectAll([]); - }; - c3_chart_internal_fn.updateXGrid = function (withoutUpdate) { - var $$ = this, config = $$.config, d3 = $$.d3, - xgridData = $$.generateGridData(config.grid_x_type, $$.x), - tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0; - - $$.xgridAttr = config.axis_rotated ? { - 'x1': 0, - 'x2': $$.width, - 'y1': function (d) { return $$.x(d) - tickOffset; }, - 'y2': function (d) { return $$.x(d) - tickOffset; } - } : { - 'x1': function (d) { return $$.x(d) + tickOffset; }, - 'x2': function (d) { return $$.x(d) + tickOffset; }, - 'y1': 0, - 'y2': $$.height - }; - - $$.xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid) - .data(xgridData); - $$.xgrid.enter().append('line').attr("class", CLASS.xgrid); - if (!withoutUpdate) { - $$.xgrid.attr($$.xgridAttr) - .style("opacity", function () { return +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1') === (config.axis_rotated ? $$.height : 0) ? 0 : 1; }); - } - $$.xgrid.exit().remove(); - }; - - c3_chart_internal_fn.updateYGrid = function () { - var $$ = this, config = $$.config, - gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks); - $$.ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid) - .data(gridValues); - $$.ygrid.enter().append('line') - .attr('class', CLASS.ygrid); - $$.ygrid.attr("x1", config.axis_rotated ? $$.y : 0) - .attr("x2", config.axis_rotated ? $$.y : $$.width) - .attr("y1", config.axis_rotated ? 0 : $$.y) - .attr("y2", config.axis_rotated ? $$.height : $$.y); - $$.ygrid.exit().remove(); - $$.smoothLines($$.ygrid, 'grid'); - }; - - c3_chart_internal_fn.gridTextAnchor = function (d) { - return d.position ? d.position : "end"; - }; - c3_chart_internal_fn.gridTextDx = function (d) { - return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4; - }; - c3_chart_internal_fn.xGridTextX = function (d) { - return d.position === 'start' ? -this.height : d.position === 'middle' ? -this.height / 2 : 0; - }; - c3_chart_internal_fn.yGridTextX = function (d) { - return d.position === 'start' ? 0 : d.position === 'middle' ? this.width / 2 : this.width; - }; - c3_chart_internal_fn.updateGrid = function (duration) { - var $$ = this, main = $$.main, config = $$.config, - xgridLine, ygridLine, yv; - - // hide if arc type - $$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible'); - - main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden"); - if (config.grid_x_show) { - $$.updateXGrid(); - } - $$.xgridLines = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine) - .data(config.grid_x_lines); - // enter - xgridLine = $$.xgridLines.enter().append('g') - .attr("class", function (d) { return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : ''); }); - xgridLine.append('line') - .style("opacity", 0); - xgridLine.append('text') - .attr("text-anchor", $$.gridTextAnchor) - .attr("transform", config.axis_rotated ? "" : "rotate(-90)") - .attr('dx', $$.gridTextDx) - .attr('dy', -5) - .style("opacity", 0); - // udpate - // done in d3.transition() of the end of this function - // exit - $$.xgridLines.exit().transition().duration(duration) - .style("opacity", 0) - .remove(); - - // Y-Grid - if (config.grid_y_show) { - $$.updateYGrid(); - } - $$.ygridLines = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine) - .data(config.grid_y_lines); - // enter - ygridLine = $$.ygridLines.enter().append('g') - .attr("class", function (d) { return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : ''); }); - ygridLine.append('line') - .style("opacity", 0); - ygridLine.append('text') - .attr("text-anchor", $$.gridTextAnchor) - .attr("transform", config.axis_rotated ? "rotate(-90)" : "") - .attr('dx', $$.gridTextDx) - .attr('dy', -5) - .style("opacity", 0); - // update - yv = $$.yv.bind($$); - $$.ygridLines.select('line') - .transition().duration(duration) - .attr("x1", config.axis_rotated ? yv : 0) - .attr("x2", config.axis_rotated ? yv : $$.width) - .attr("y1", config.axis_rotated ? 0 : yv) - .attr("y2", config.axis_rotated ? $$.height : yv) - .style("opacity", 1); - $$.ygridLines.select('text') - .transition().duration(duration) - .attr("x", config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$)) - .attr("y", yv) - .text(function (d) { return d.text; }) - .style("opacity", 1); - // exit - $$.ygridLines.exit().transition().duration(duration) - .style("opacity", 0) - .remove(); - }; - c3_chart_internal_fn.redrawGrid = function (withTransition) { - var $$ = this, config = $$.config, xv = $$.xv.bind($$), - lines = $$.xgridLines.select('line'), - texts = $$.xgridLines.select('text'); - return [ - (withTransition ? lines.transition() : lines) - .attr("x1", config.axis_rotated ? 0 : xv) - .attr("x2", config.axis_rotated ? $$.width : xv) - .attr("y1", config.axis_rotated ? xv : 0) - .attr("y2", config.axis_rotated ? xv : $$.height) - .style("opacity", 1), - (withTransition ? texts.transition() : texts) - .attr("x", config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$)) - .attr("y", xv) - .text(function (d) { return d.text; }) - .style("opacity", 1) - ]; - }; - c3_chart_internal_fn.showXGridFocus = function (selectedData) { - var $$ = this, config = $$.config, - dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }), - focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus), - xx = $$.xx.bind($$); - if (! config.tooltip_show) { return; } - // Hide when scatter plot exists - if ($$.hasType('scatter') || $$.hasArcType()) { return; } - focusEl - .style("visibility", "visible") - .data([dataToShow[0]]) - .attr(config.axis_rotated ? 'y1' : 'x1', xx) - .attr(config.axis_rotated ? 'y2' : 'x2', xx); - $$.smoothLines(focusEl, 'grid'); - }; - c3_chart_internal_fn.hideXGridFocus = function () { - this.main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden"); - }; - c3_chart_internal_fn.updateXgridFocus = function () { - var $$ = this, config = $$.config; - $$.main.select('line.' + CLASS.xgridFocus) - .attr("x1", config.axis_rotated ? 0 : -10) - .attr("x2", config.axis_rotated ? $$.width : -10) - .attr("y1", config.axis_rotated ? -10 : 0) - .attr("y2", config.axis_rotated ? -10 : $$.height); - }; - c3_chart_internal_fn.generateGridData = function (type, scale) { - var $$ = this, - gridData = [], xDomain, firstYear, lastYear, i, - tickNum = $$.main.select("." + CLASS.axisX).selectAll('.tick').size(); - if (type === 'year') { - xDomain = $$.getXDomain(); - firstYear = xDomain[0].getFullYear(); - lastYear = xDomain[1].getFullYear(); - for (i = firstYear; i <= lastYear; i++) { - gridData.push(new Date(i + '-01-01 00:00:00')); - } - } else { - gridData = scale.ticks(10); - if (gridData.length > tickNum) { // use only int - gridData = gridData.filter(function (d) { return ("" + d).indexOf('.') < 0; }); - } - } - return gridData; - }; - c3_chart_internal_fn.getGridFilterToRemove = function (params) { - return params ? function (line) { - var found = false; - [].concat(params).forEach(function (param) { - if ((('value' in param && line.value === param.value) || ('class' in param && line['class'] === param['class']))) { - found = true; - } - }); - return found; - } : function () { return true; }; - }; - c3_chart_internal_fn.removeGridLines = function (params, forX) { - var $$ = this, config = $$.config, - toRemove = $$.getGridFilterToRemove(params), - toShow = function (line) { return !toRemove(line); }, - classLines = forX ? CLASS.xgridLines : CLASS.ygridLines, - classLine = forX ? CLASS.xgridLine : CLASS.ygridLine; - $$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove) - .transition().duration(config.transition_duration) - .style('opacity', 0).remove(); - if (forX) { - config.grid_x_lines = config.grid_x_lines.filter(toShow); - } else { - config.grid_y_lines = config.grid_y_lines.filter(toShow); - } - }; - - c3_chart_internal_fn.initTooltip = function () { - var $$ = this, config = $$.config, i; - $$.tooltip = $$.selectChart - .style("position", "relative") - .append("div") - .attr('class', CLASS.tooltipContainer) - .style("position", "absolute") - .style("pointer-events", "none") - .style("display", "none"); - // Show tooltip if needed - if (config.tooltip_init_show) { - if ($$.isTimeSeries() && isString(config.tooltip_init_x)) { - config.tooltip_init_x = $$.parseDate(config.tooltip_init_x); - for (i = 0; i < $$.data.targets[0].values.length; i++) { - if (($$.data.targets[0].values[i].x - config.tooltip_init_x) === 0) { break; } - } - config.tooltip_init_x = i; - } - $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) { - return $$.addName(d.values[config.tooltip_init_x]); - }), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color)); - $$.tooltip.style("top", config.tooltip_init_position.top) - .style("left", config.tooltip_init_position.left) - .style("display", "block"); - } - }; - c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) { - var $$ = this, config = $$.config, - titleFormat = config.tooltip_format_title || defaultTitleFormat, - nameFormat = config.tooltip_format_name || function (name) { return name; }, - valueFormat = config.tooltip_format_value || defaultValueFormat, - text, i, title, value, name, bgcolor, - orderAsc = $$.isOrderAsc(); - - if (config.data_groups.length === 0) { - d.sort(function(a, b){ - var v1 = a ? a.value : null, v2 = b ? b.value : null; - return orderAsc ? v1 - v2 : v2 - v1; - }); - } else { - var ids = $$.orderTargets($$.data.targets).map(function (i) { - return i.id; - }); - d.sort(function(a, b) { - var v1 = a ? a.value : null, v2 = b ? b.value : null; - if (v1 > 0 && v2 > 0) { - v1 = a ? ids.indexOf(a.id) : null; - v2 = b ? ids.indexOf(b.id) : null; - } - return orderAsc ? v1 - v2 : v2 - v1; - }); - } - - for (i = 0; i < d.length; i++) { - if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; } - - if (! text) { - title = sanitise(titleFormat ? titleFormat(d[i].x) : d[i].x); - text = "" + (title || title === 0 ? "" : ""); - } - - value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d)); - if (value !== undefined) { - // Skip elements when their name is set to null - if (d[i].name === null) { continue; } - name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index)); - bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id); - - text += ""; - text += ""; - text += ""; - text += ""; - } - } - return text + "
" + title + "
" + name + "" + value + "
"; - }; - c3_chart_internal_fn.tooltipPosition = function (dataToShow, tWidth, tHeight, element) { - var $$ = this, config = $$.config, d3 = $$.d3; - var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight; - var forArc = $$.hasArcType(), - mouse = d3.mouse(element); - // Determin tooltip position - if (forArc) { - tooltipLeft = (($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2) + mouse[0]; - tooltipTop = ($$.height / 2) + mouse[1] + 20; - } else { - svgLeft = $$.getSvgLeft(true); - if (config.axis_rotated) { - tooltipLeft = svgLeft + mouse[0] + 100; - tooltipRight = tooltipLeft + tWidth; - chartRight = $$.currentWidth - $$.getCurrentPaddingRight(); - tooltipTop = $$.x(dataToShow[0].x) + 20; - } else { - tooltipLeft = svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20; - tooltipRight = tooltipLeft + tWidth; - chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight(); - tooltipTop = mouse[1] + 15; - } - - if (tooltipRight > chartRight) { - // 20 is needed for Firefox to keep tooltip width - tooltipLeft -= tooltipRight - chartRight + 20; - } - if (tooltipTop + tHeight > $$.currentHeight) { - tooltipTop -= tHeight + 30; - } - } - if (tooltipTop < 0) { - tooltipTop = 0; - } - return {top: tooltipTop, left: tooltipLeft}; - }; - c3_chart_internal_fn.showTooltip = function (selectedData, element) { - var $$ = this, config = $$.config; - var tWidth, tHeight, position; - var forArc = $$.hasArcType(), - dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }), - positionFunction = config.tooltip_position || c3_chart_internal_fn.tooltipPosition; - if (dataToShow.length === 0 || !config.tooltip_show) { - return; - } - $$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style("display", "block"); - - // Get tooltip dimensions - tWidth = $$.tooltip.property('offsetWidth'); - tHeight = $$.tooltip.property('offsetHeight'); - - position = positionFunction.call(this, dataToShow, tWidth, tHeight, element); - // Set tooltip - $$.tooltip - .style("top", position.top + "px") - .style("left", position.left + 'px'); - }; - c3_chart_internal_fn.hideTooltip = function () { - this.tooltip.style("display", "none"); - }; - - c3_chart_internal_fn.initLegend = function () { - var $$ = this; - $$.legendItemTextBox = {}; - $$.legendHasRendered = false; - $$.legend = $$.svg.append("g").attr("transform", $$.getTranslate('legend')); - if (!$$.config.legend_show) { - $$.legend.style('visibility', 'hidden'); - $$.hiddenLegendIds = $$.mapToIds($$.data.targets); - return; - } - // MEMO: call here to update legend box and tranlate for all - // MEMO: translate will be upated by this, so transform not needed in updateLegend() - $$.updateLegendWithDefaults(); - }; - c3_chart_internal_fn.updateLegendWithDefaults = function () { - var $$ = this; - $$.updateLegend($$.mapToIds($$.data.targets), {withTransform: false, withTransitionForTransform: false, withTransition: false}); - }; - c3_chart_internal_fn.updateSizeForLegend = function (legendHeight, legendWidth) { - var $$ = this, config = $$.config, insetLegendPosition = { - top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y, - left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5 - }; - - $$.margin3 = { - top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight, - right: NaN, - bottom: 0, - left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0 - }; - }; - c3_chart_internal_fn.transformLegend = function (withTransition) { - var $$ = this; - (withTransition ? $$.legend.transition() : $$.legend).attr("transform", $$.getTranslate('legend')); - }; - c3_chart_internal_fn.updateLegendStep = function (step) { - this.legendStep = step; - }; - c3_chart_internal_fn.updateLegendItemWidth = function (w) { - this.legendItemWidth = w; - }; - c3_chart_internal_fn.updateLegendItemHeight = function (h) { - this.legendItemHeight = h; - }; - c3_chart_internal_fn.getLegendWidth = function () { - var $$ = this; - return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0; - }; - c3_chart_internal_fn.getLegendHeight = function () { - var $$ = this, h = 0; - if ($$.config.legend_show) { - if ($$.isLegendRight) { - h = $$.currentHeight; - } else { - h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1); - } - } - return h; - }; - c3_chart_internal_fn.opacityForLegend = function (legendItem) { - return legendItem.classed(CLASS.legendItemHidden) ? null : 1; - }; - c3_chart_internal_fn.opacityForUnfocusedLegend = function (legendItem) { - return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3; - }; - c3_chart_internal_fn.toggleFocusLegend = function (targetIds, focus) { - var $$ = this; - targetIds = $$.mapToTargetIds(targetIds); - $$.legend.selectAll('.' + CLASS.legendItem) - .filter(function (id) { return targetIds.indexOf(id) >= 0; }) - .classed(CLASS.legendItemFocused, focus) - .transition().duration(100) - .style('opacity', function () { - var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend; - return opacity.call($$, $$.d3.select(this)); - }); - }; - c3_chart_internal_fn.revertLegend = function () { - var $$ = this, d3 = $$.d3; - $$.legend.selectAll('.' + CLASS.legendItem) - .classed(CLASS.legendItemFocused, false) - .transition().duration(100) - .style('opacity', function () { return $$.opacityForLegend(d3.select(this)); }); - }; - c3_chart_internal_fn.showLegend = function (targetIds) { - var $$ = this, config = $$.config; - if (!config.legend_show) { - config.legend_show = true; - $$.legend.style('visibility', 'visible'); - if (!$$.legendHasRendered) { - $$.updateLegendWithDefaults(); - } - } - $$.removeHiddenLegendIds(targetIds); - $$.legend.selectAll($$.selectorLegends(targetIds)) - .style('visibility', 'visible') - .transition() - .style('opacity', function () { return $$.opacityForLegend($$.d3.select(this)); }); - }; - c3_chart_internal_fn.hideLegend = function (targetIds) { - var $$ = this, config = $$.config; - if (config.legend_show && isEmpty(targetIds)) { - config.legend_show = false; - $$.legend.style('visibility', 'hidden'); - } - $$.addHiddenLegendIds(targetIds); - $$.legend.selectAll($$.selectorLegends(targetIds)) - .style('opacity', 0) - .style('visibility', 'hidden'); - }; - c3_chart_internal_fn.clearLegendItemTextBoxCache = function () { - this.legendItemTextBox = {}; - }; - c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) { - var $$ = this, config = $$.config; - var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect, x1ForLegendTile, x2ForLegendTile, yForLegendTile; - var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = config.legend_item_tile_width + 5; - var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0; - var withTransition, withTransitionForTransform; - var texts, rects, tiles, background; - - // Skip elements when their name is set to null - targetIds = targetIds.filter(function(id) { - return !isDefined(config.data_names[id]) || config.data_names[id] !== null; - }); - - options = options || {}; - withTransition = getOption(options, "withTransition", true); - withTransitionForTransform = getOption(options, "withTransitionForTransform", true); - - function getTextBox(textElement, id) { - if (!$$.legendItemTextBox[id]) { - $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem, textElement); - } - return $$.legendItemTextBox[id]; - } - - function updatePositions(textElement, id, index) { - var reset = index === 0, isLast = index === targetIds.length - 1, - box = getTextBox(textElement, id), - itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) + config.legend_padding, - itemHeight = box.height + paddingTop, - itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth, - areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(), - margin, maxLength; - - // MEMO: care about condifion of step, totalLength - function updateValues(id, withoutStep) { - if (!withoutStep) { - margin = (areaLength - totalLength - itemLength) / 2; - if (margin < posMin) { - margin = (areaLength - itemLength) / 2; - totalLength = 0; - step++; - } - } - steps[id] = step; - margins[step] = $$.isLegendInset ? 10 : margin; - offsets[id] = totalLength; - totalLength += itemLength; - } - - if (reset) { - totalLength = 0; - step = 0; - maxWidth = 0; - maxHeight = 0; - } - - if (config.legend_show && !$$.isLegendToShow(id)) { - widths[id] = heights[id] = steps[id] = offsets[id] = 0; - return; - } - - widths[id] = itemWidth; - heights[id] = itemHeight; - - if (!maxWidth || itemWidth >= maxWidth) { maxWidth = itemWidth; } - if (!maxHeight || itemHeight >= maxHeight) { maxHeight = itemHeight; } - maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth; - - if (config.legend_equally) { - Object.keys(widths).forEach(function (id) { widths[id] = maxWidth; }); - Object.keys(heights).forEach(function (id) { heights[id] = maxHeight; }); - margin = (areaLength - maxLength * targetIds.length) / 2; - if (margin < posMin) { - totalLength = 0; - step = 0; - targetIds.forEach(function (id) { updateValues(id); }); - } - else { - updateValues(id, true); - } - } else { - updateValues(id); - } - } - - if ($$.isLegendInset) { - step = config.legend_inset_step ? config.legend_inset_step : targetIds.length; - $$.updateLegendStep(step); - } - - if ($$.isLegendRight) { - xForLegend = function (id) { return maxWidth * steps[id]; }; - yForLegend = function (id) { return margins[steps[id]] + offsets[id]; }; - } else if ($$.isLegendInset) { - xForLegend = function (id) { return maxWidth * steps[id] + 10; }; - yForLegend = function (id) { return margins[steps[id]] + offsets[id]; }; - } else { - xForLegend = function (id) { return margins[steps[id]] + offsets[id]; }; - yForLegend = function (id) { return maxHeight * steps[id]; }; - } - xForLegendText = function (id, i) { return xForLegend(id, i) + 4 + config.legend_item_tile_width; }; - yForLegendText = function (id, i) { return yForLegend(id, i) + 9; }; - xForLegendRect = function (id, i) { return xForLegend(id, i); }; - yForLegendRect = function (id, i) { return yForLegend(id, i) - 5; }; - x1ForLegendTile = function (id, i) { return xForLegend(id, i) - 2; }; - x2ForLegendTile = function (id, i) { return xForLegend(id, i) - 2 + config.legend_item_tile_width; }; - yForLegendTile = function (id, i) { return yForLegend(id, i) + 4; }; - - // Define g for legend area - l = $$.legend.selectAll('.' + CLASS.legendItem) - .data(targetIds) - .enter().append('g') - .attr('class', function (id) { return $$.generateClass(CLASS.legendItem, id); }) - .style('visibility', function (id) { return $$.isLegendToShow(id) ? 'visible' : 'hidden'; }) - .style('cursor', 'pointer') - .on('click', function (id) { - if (config.legend_item_onclick) { - config.legend_item_onclick.call($$, id); - } else { - if ($$.d3.event.altKey) { - $$.api.hide(); - $$.api.show(id); - } else { - $$.api.toggle(id); - $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert(); - } - } - }) - .on('mouseover', function (id) { - if (config.legend_item_onmouseover) { - config.legend_item_onmouseover.call($$, id); - } - else { - $$.d3.select(this).classed(CLASS.legendItemFocused, true); - if (!$$.transiting && $$.isTargetToShow(id)) { - $$.api.focus(id); - } - } - }) - .on('mouseout', function (id) { - if (config.legend_item_onmouseout) { - config.legend_item_onmouseout.call($$, id); - } - else { - $$.d3.select(this).classed(CLASS.legendItemFocused, false); - $$.api.revert(); - } - }); - l.append('text') - .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) - .each(function (id, i) { updatePositions(this, id, i); }) - .style("pointer-events", "none") - .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200) - .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText); - l.append('rect') - .attr("class", CLASS.legendItemEvent) - .style('fill-opacity', 0) - .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200) - .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect); - l.append('line') - .attr('class', CLASS.legendItemTile) - .style('stroke', $$.color) - .style("pointer-events", "none") - .attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200) - .attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile) - .attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200) - .attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile) - .attr('stroke-width', config.legend_item_tile_height); - - // Set background for inset legend - background = $$.legend.select('.' + CLASS.legendBackground + ' rect'); - if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) { - background = $$.legend.insert('g', '.' + CLASS.legendItem) - .attr("class", CLASS.legendBackground) - .append('rect'); - } - - texts = $$.legend.selectAll('text') - .data(targetIds) - .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) // MEMO: needed for update - .each(function (id, i) { updatePositions(this, id, i); }); - (withTransition ? texts.transition() : texts) - .attr('x', xForLegendText) - .attr('y', yForLegendText); - - rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent) - .data(targetIds); - (withTransition ? rects.transition() : rects) - .attr('width', function (id) { return widths[id]; }) - .attr('height', function (id) { return heights[id]; }) - .attr('x', xForLegendRect) - .attr('y', yForLegendRect); - - tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile) - .data(targetIds); - (withTransition ? tiles.transition() : tiles) - .style('stroke', $$.color) - .attr('x1', x1ForLegendTile) - .attr('y1', yForLegendTile) - .attr('x2', x2ForLegendTile) - .attr('y2', yForLegendTile); - - if (background) { - (withTransition ? background.transition() : background) - .attr('height', $$.getLegendHeight() - 12) - .attr('width', maxWidth * (step + 1) + 10); - } - - // toggle legend state - $$.legend.selectAll('.' + CLASS.legendItem) - .classed(CLASS.legendItemHidden, function (id) { return !$$.isTargetToShow(id); }); - - // Update all to reflect change of legend - $$.updateLegendItemWidth(maxWidth); - $$.updateLegendItemHeight(maxHeight); - $$.updateLegendStep(step); - // Update size and scale - $$.updateSizes(); - $$.updateScales(); - $$.updateSvgSize(); - // Update g positions - $$.transformAll(withTransitionForTransform, transitions); - $$.legendHasRendered = true; - }; - - c3_chart_internal_fn.initTitle = function () { - var $$ = this; - $$.title = $$.svg.append("text") - .text($$.config.title_text) - .attr("class", $$.CLASS.title); - }; - c3_chart_internal_fn.redrawTitle = function () { - var $$ = this; - $$.title - .attr("x", $$.xForTitle.bind($$)) - .attr("y", $$.yForTitle.bind($$)); - }; - c3_chart_internal_fn.xForTitle = function () { - var $$ = this, config = $$.config, position = config.title_position || 'left', x; - if (position.indexOf('right') >= 0) { - x = $$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width - config.title_padding.right; - } else if (position.indexOf('center') >= 0) { - x = ($$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width) / 2; - } else { // left - x = config.title_padding.left; - } - return x; - }; - c3_chart_internal_fn.yForTitle = function () { - var $$ = this; - return $$.config.title_padding.top + $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).height; - }; - c3_chart_internal_fn.getTitlePadding = function() { - var $$ = this; - return $$.yForTitle() + $$.config.title_padding.bottom; - }; - - function Axis(owner) { - API.call(this, owner); - } - - inherit(API, Axis); - - Axis.prototype.init = function init() { - - var $$ = this.owner, config = $$.config, main = $$.main; - $$.axes.x = main.append("g") - .attr("class", CLASS.axis + ' ' + CLASS.axisX) - .attr("clip-path", $$.clipPathForXAxis) - .attr("transform", $$.getTranslate('x')) - .style("visibility", config.axis_x_show ? 'visible' : 'hidden'); - $$.axes.x.append("text") - .attr("class", CLASS.axisXLabel) - .attr("transform", config.axis_rotated ? "rotate(-90)" : "") - .style("text-anchor", this.textAnchorForXAxisLabel.bind(this)); - $$.axes.y = main.append("g") - .attr("class", CLASS.axis + ' ' + CLASS.axisY) - .attr("clip-path", config.axis_y_inner ? "" : $$.clipPathForYAxis) - .attr("transform", $$.getTranslate('y')) - .style("visibility", config.axis_y_show ? 'visible' : 'hidden'); - $$.axes.y.append("text") - .attr("class", CLASS.axisYLabel) - .attr("transform", config.axis_rotated ? "" : "rotate(-90)") - .style("text-anchor", this.textAnchorForYAxisLabel.bind(this)); - - $$.axes.y2 = main.append("g") - .attr("class", CLASS.axis + ' ' + CLASS.axisY2) - // clip-path? - .attr("transform", $$.getTranslate('y2')) - .style("visibility", config.axis_y2_show ? 'visible' : 'hidden'); - $$.axes.y2.append("text") - .attr("class", CLASS.axisY2Label) - .attr("transform", config.axis_rotated ? "" : "rotate(-90)") - .style("text-anchor", this.textAnchorForY2AxisLabel.bind(this)); - }; - Axis.prototype.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) { - var $$ = this.owner, config = $$.config, - axisParams = { - isCategory: $$.isCategorized(), - withOuterTick: withOuterTick, - tickMultiline: config.axis_x_tick_multiline, - tickWidth: config.axis_x_tick_width, - tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate, - withoutTransition: withoutTransition, - }, - axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient); - - if ($$.isTimeSeries() && tickValues && typeof tickValues !== "function") { - tickValues = tickValues.map(function (v) { return $$.parseDate(v); }); - } - - // Set tick - axis.tickFormat(tickFormat).tickValues(tickValues); - if ($$.isCategorized()) { - axis.tickCentered(config.axis_x_tick_centered); - if (isEmpty(config.axis_x_tick_culling)) { - config.axis_x_tick_culling = false; - } - } - - return axis; - }; - Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) { - var $$ = this.owner, config = $$.config, tickValues; - if (config.axis_x_tick_fit || config.axis_x_tick_count) { - tickValues = this.generateTickValues($$.mapTargetsToUniqueXs(targets), config.axis_x_tick_count, $$.isTimeSeries()); - } - if (axis) { - axis.tickValues(tickValues); - } else { - $$.xAxis.tickValues(tickValues); - $$.subXAxis.tickValues(tickValues); - } - return tickValues; - }; - Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) { - var $$ = this.owner, config = $$.config, - axisParams = { - withOuterTick: withOuterTick, - withoutTransition: withoutTransition, - tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate - }, - axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat); - if ($$.isTimeSeriesY()) { - axis.ticks($$.d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval); - } else { - axis.tickValues(tickValues); - } - return axis; - }; - Axis.prototype.getId = function getId(id) { - var config = this.owner.config; - return id in config.data_axes ? config.data_axes[id] : 'y'; - }; - Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() { - var $$ = this.owner, config = $$.config, - format = $$.isTimeSeries() ? $$.defaultAxisTimeFormat : $$.isCategorized() ? $$.categoryName : function (v) { return v < 0 ? v.toFixed(0) : v; }; - if (config.axis_x_tick_format) { - if (isFunction(config.axis_x_tick_format)) { - format = config.axis_x_tick_format; - } else if ($$.isTimeSeries()) { - format = function (date) { - return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : ""; - }; - } - } - return isFunction(format) ? function (v) { return format.call($$, v); } : format; - }; - Axis.prototype.getTickValues = function getTickValues(tickValues, axis) { - return tickValues ? tickValues : axis ? axis.tickValues() : undefined; - }; - Axis.prototype.getXAxisTickValues = function getXAxisTickValues() { - return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis); - }; - Axis.prototype.getYAxisTickValues = function getYAxisTickValues() { - return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis); - }; - Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() { - return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis); - }; - Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) { - var $$ = this.owner, config = $$.config, option; - if (axisId === 'y') { - option = config.axis_y_label; - } else if (axisId === 'y2') { - option = config.axis_y2_label; - } else if (axisId === 'x') { - option = config.axis_x_label; - } - return option; - }; - Axis.prototype.getLabelText = function getLabelText(axisId) { - var option = this.getLabelOptionByAxisId(axisId); - return isString(option) ? option : option ? option.text : null; - }; - Axis.prototype.setLabelText = function setLabelText(axisId, text) { - var $$ = this.owner, config = $$.config, - option = this.getLabelOptionByAxisId(axisId); - if (isString(option)) { - if (axisId === 'y') { - config.axis_y_label = text; - } else if (axisId === 'y2') { - config.axis_y2_label = text; - } else if (axisId === 'x') { - config.axis_x_label = text; - } - } else if (option) { - option.text = text; - } - }; - Axis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) { - var option = this.getLabelOptionByAxisId(axisId), - position = (option && typeof option === 'object' && option.position) ? option.position : defaultPosition; - return { - isInner: position.indexOf('inner') >= 0, - isOuter: position.indexOf('outer') >= 0, - isLeft: position.indexOf('left') >= 0, - isCenter: position.indexOf('center') >= 0, - isRight: position.indexOf('right') >= 0, - isTop: position.indexOf('top') >= 0, - isMiddle: position.indexOf('middle') >= 0, - isBottom: position.indexOf('bottom') >= 0 - }; - }; - Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() { - return this.getLabelPosition('x', this.owner.config.axis_rotated ? 'inner-top' : 'inner-right'); - }; - Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() { - return this.getLabelPosition('y', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top'); - }; - Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() { - return this.getLabelPosition('y2', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top'); - }; - Axis.prototype.getLabelPositionById = function getLabelPositionById(id) { - return id === 'y2' ? this.getY2AxisLabelPosition() : id === 'y' ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition(); - }; - Axis.prototype.textForXAxisLabel = function textForXAxisLabel() { - return this.getLabelText('x'); - }; - Axis.prototype.textForYAxisLabel = function textForYAxisLabel() { - return this.getLabelText('y'); - }; - Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() { - return this.getLabelText('y2'); - }; - Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) { - var $$ = this.owner; - if (forHorizontal) { - return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width; - } else { - return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0; - } - }; - Axis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) { - if (forHorizontal) { - return position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0"; - } else { - return position.isTop ? "-0.5em" : position.isBottom ? "0.5em" : "0"; - } - }; - Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) { - if (forHorizontal) { - return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end'; - } else { - return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end'; - } - }; - Axis.prototype.xForXAxisLabel = function xForXAxisLabel() { - return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition()); - }; - Axis.prototype.xForYAxisLabel = function xForYAxisLabel() { - return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition()); - }; - Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() { - return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition()); - }; - Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() { - return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition()); - }; - Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() { - return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition()); - }; - Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() { - return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition()); - }; - Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() { - var $$ = this.owner, config = $$.config, - position = this.getXAxisLabelPosition(); - if (config.axis_rotated) { - return position.isInner ? "1.2em" : -25 - this.getMaxTickWidth('x'); - } else { - return position.isInner ? "-0.5em" : config.axis_x_height ? config.axis_x_height - 10 : "3em"; - } - }; - Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() { - var $$ = this.owner, - position = this.getYAxisLabelPosition(); - if ($$.config.axis_rotated) { - return position.isInner ? "-0.5em" : "3em"; - } else { - return position.isInner ? "1.2em" : -10 - ($$.config.axis_y_inner ? 0 : (this.getMaxTickWidth('y') + 10)); - } - }; - Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() { - var $$ = this.owner, - position = this.getY2AxisLabelPosition(); - if ($$.config.axis_rotated) { - return position.isInner ? "1.2em" : "-2.2em"; - } else { - return position.isInner ? "-0.5em" : 15 + ($$.config.axis_y2_inner ? 0 : (this.getMaxTickWidth('y2') + 15)); - } - }; - Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() { - var $$ = this.owner; - return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition()); - }; - Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() { - var $$ = this.owner; - return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition()); - }; - Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() { - var $$ = this.owner; - return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition()); - }; - Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) { - var $$ = this.owner, config = $$.config, - maxWidth = 0, targetsToShow, scale, axis, dummy, svg; - if (withoutRecompute && $$.currentMaxTickWidths[id]) { - return $$.currentMaxTickWidths[id]; - } - if ($$.svg) { - targetsToShow = $$.filterTargetsToShow($$.data.targets); - if (id === 'y') { - scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y')); - axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true, true); - } else if (id === 'y2') { - scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2')); - axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true, true); - } else { - scale = $$.x.copy().domain($$.getXDomain(targetsToShow)); - axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true); - this.updateXAxisTickValues(targetsToShow, axis); - } - dummy = $$.d3.select('body').append('div').classed('c3', true); - svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0), - svg.append('g').call(axis).each(function () { - $$.d3.select(this).selectAll('text').each(function () { - var box = this.getBoundingClientRect(); - if (maxWidth < box.width) { maxWidth = box.width; } - }); - dummy.remove(); - }); - } - $$.currentMaxTickWidths[id] = maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth; - return $$.currentMaxTickWidths[id]; - }; - - Axis.prototype.updateLabels = function updateLabels(withTransition) { - var $$ = this.owner; - var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel), - axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel), - axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label); - (withTransition ? axisXLabel.transition() : axisXLabel) - .attr("x", this.xForXAxisLabel.bind(this)) - .attr("dx", this.dxForXAxisLabel.bind(this)) - .attr("dy", this.dyForXAxisLabel.bind(this)) - .text(this.textForXAxisLabel.bind(this)); - (withTransition ? axisYLabel.transition() : axisYLabel) - .attr("x", this.xForYAxisLabel.bind(this)) - .attr("dx", this.dxForYAxisLabel.bind(this)) - .attr("dy", this.dyForYAxisLabel.bind(this)) - .text(this.textForYAxisLabel.bind(this)); - (withTransition ? axisY2Label.transition() : axisY2Label) - .attr("x", this.xForY2AxisLabel.bind(this)) - .attr("dx", this.dxForY2AxisLabel.bind(this)) - .attr("dy", this.dyForY2AxisLabel.bind(this)) - .text(this.textForY2AxisLabel.bind(this)); - }; - Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) { - var p = typeof padding === 'number' ? padding : padding[key]; - if (!isValue(p)) { - return defaultValue; - } - if (padding.unit === 'ratio') { - return padding[key] * domainLength; - } - // assume padding is pixels if unit is not specified - return this.convertPixelsToAxisPadding(p, domainLength); - }; - Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) { - var $$ = this.owner, - length = $$.config.axis_rotated ? $$.width : $$.height; - return domainLength * (pixels / length); - }; - Axis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) { - var tickValues = values, targetCount, start, end, count, interval, i, tickValue; - if (tickCount) { - targetCount = isFunction(tickCount) ? tickCount() : tickCount; - // compute ticks according to tickCount - if (targetCount === 1) { - tickValues = [values[0]]; - } else if (targetCount === 2) { - tickValues = [values[0], values[values.length - 1]]; - } else if (targetCount > 2) { - count = targetCount - 2; - start = values[0]; - end = values[values.length - 1]; - interval = (end - start) / (count + 1); - // re-construct unique values - tickValues = [start]; - for (i = 0; i < count; i++) { - tickValue = +start + interval * (i + 1); - tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue); - } - tickValues.push(end); - } - } - if (!forTimeSeries) { tickValues = tickValues.sort(function (a, b) { return a - b; }); } - return tickValues; - }; - Axis.prototype.generateTransitions = function generateTransitions(duration) { - var $$ = this.owner, axes = $$.axes; - return { - axisX: duration ? axes.x.transition().duration(duration) : axes.x, - axisY: duration ? axes.y.transition().duration(duration) : axes.y, - axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2, - axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx - }; - }; - Axis.prototype.redraw = function redraw(transitions, isHidden) { - var $$ = this.owner; - $$.axes.x.style("opacity", isHidden ? 0 : 1); - $$.axes.y.style("opacity", isHidden ? 0 : 1); - $$.axes.y2.style("opacity", isHidden ? 0 : 1); - $$.axes.subx.style("opacity", isHidden ? 0 : 1); - transitions.axisX.call($$.xAxis); - transitions.axisY.call($$.yAxis); - transitions.axisY2.call($$.y2Axis); - transitions.axisSubX.call($$.subXAxis); - }; - - c3_chart_internal_fn.getClipPath = function (id) { - var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0; - return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")"; - }; - c3_chart_internal_fn.appendClip = function (parent, id) { - return parent.append("clipPath").attr("id", id).append("rect"); - }; - c3_chart_internal_fn.getAxisClipX = function (forHorizontal) { - // axis line width + padding for left - var left = Math.max(30, this.margin.left); - return forHorizontal ? -(1 + left) : -(left - 1); - }; - c3_chart_internal_fn.getAxisClipY = function (forHorizontal) { - return forHorizontal ? -20 : -this.margin.top; - }; - c3_chart_internal_fn.getXAxisClipX = function () { - var $$ = this; - return $$.getAxisClipX(!$$.config.axis_rotated); - }; - c3_chart_internal_fn.getXAxisClipY = function () { - var $$ = this; - return $$.getAxisClipY(!$$.config.axis_rotated); - }; - c3_chart_internal_fn.getYAxisClipX = function () { - var $$ = this; - return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated); - }; - c3_chart_internal_fn.getYAxisClipY = function () { - var $$ = this; - return $$.getAxisClipY($$.config.axis_rotated); - }; - c3_chart_internal_fn.getAxisClipWidth = function (forHorizontal) { - var $$ = this, - left = Math.max(30, $$.margin.left), - right = Math.max(30, $$.margin.right); - // width + axis line width + padding for left/right - return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20; - }; - c3_chart_internal_fn.getAxisClipHeight = function (forHorizontal) { - // less than 20 is not enough to show the axis label 'outer' without legend - return (forHorizontal ? this.margin.bottom : (this.margin.top + this.height)) + 20; - }; - c3_chart_internal_fn.getXAxisClipWidth = function () { - var $$ = this; - return $$.getAxisClipWidth(!$$.config.axis_rotated); - }; - c3_chart_internal_fn.getXAxisClipHeight = function () { - var $$ = this; - return $$.getAxisClipHeight(!$$.config.axis_rotated); - }; - c3_chart_internal_fn.getYAxisClipWidth = function () { - var $$ = this; - return $$.getAxisClipWidth($$.config.axis_rotated) + ($$.config.axis_y_inner ? 20 : 0); - }; - c3_chart_internal_fn.getYAxisClipHeight = function () { - var $$ = this; - return $$.getAxisClipHeight($$.config.axis_rotated); - }; - - c3_chart_internal_fn.initPie = function () { - var $$ = this, d3 = $$.d3, config = $$.config; - $$.pie = d3.layout.pie().value(function (d) { - return d.values.reduce(function (a, b) { return a + b.value; }, 0); - }); - if (!config.data_order) { - $$.pie.sort(null); - } - }; - - c3_chart_internal_fn.updateRadius = function () { - var $$ = this, config = $$.config, - w = config.gauge_width || config.donut_width; - $$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2; - $$.radius = $$.radiusExpanded * 0.95; - $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6; - $$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0; - }; - - c3_chart_internal_fn.updateArc = function () { - var $$ = this; - $$.svgArc = $$.getSvgArc(); - $$.svgArcExpanded = $$.getSvgArcExpanded(); - $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98); - }; - - c3_chart_internal_fn.updateAngle = function (d) { - var $$ = this, config = $$.config, - found = false, index = 0, - gMin, gMax, gTic, gValue; - - if (!config) { - return null; - } - - $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) { - if (! found && t.data.id === d.data.id) { - found = true; - d = t; - d.index = index; - } - index++; - }); - if (isNaN(d.startAngle)) { - d.startAngle = 0; - } - if (isNaN(d.endAngle)) { - d.endAngle = d.startAngle; - } - if ($$.isGaugeType(d.data)) { - gMin = config.gauge_min; - gMax = config.gauge_max; - gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin); - gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin); - d.startAngle = config.gauge_startingAngle; - d.endAngle = d.startAngle + gTic * gValue; - } - return found ? d : null; - }; - - c3_chart_internal_fn.getSvgArc = function () { - var $$ = this, - arc = $$.d3.svg.arc().outerRadius($$.radius).innerRadius($$.innerRadius), - newArc = function (d, withoutUpdate) { - var updated; - if (withoutUpdate) { return arc(d); } // for interpolate - updated = $$.updateAngle(d); - return updated ? arc(updated) : "M 0 0"; - }; - // TODO: extends all function - newArc.centroid = arc.centroid; - return newArc; - }; - - c3_chart_internal_fn.getSvgArcExpanded = function (rate) { - var $$ = this, - arc = $$.d3.svg.arc().outerRadius($$.radiusExpanded * (rate ? rate : 1)).innerRadius($$.innerRadius); - return function (d) { - var updated = $$.updateAngle(d); - return updated ? arc(updated) : "M 0 0"; - }; - }; - - c3_chart_internal_fn.getArc = function (d, withoutUpdate, force) { - return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0"; - }; - - - c3_chart_internal_fn.transformForArcLabel = function (d) { - var $$ = this, config = $$.config, - updated = $$.updateAngle(d), c, x, y, h, ratio, translate = ""; - if (updated && !$$.hasType('gauge')) { - c = this.svgArc.centroid(updated); - x = isNaN(c[0]) ? 0 : c[0]; - y = isNaN(c[1]) ? 0 : c[1]; - h = Math.sqrt(x * x + y * y); - if ($$.hasType('donut') && config.donut_label_ratio) { - ratio = isFunction(config.donut_label_ratio) ? config.donut_label_ratio(d, $$.radius, h) : config.donut_label_ratio; - } else if ($$.hasType('pie') && config.pie_label_ratio) { - ratio = isFunction(config.pie_label_ratio) ? config.pie_label_ratio(d, $$.radius, h) : config.pie_label_ratio; - } else { - ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0; - } - translate = "translate(" + (x * ratio) + ',' + (y * ratio) + ")"; - } - return translate; - }; - - c3_chart_internal_fn.getArcRatio = function (d) { - var $$ = this, - config = $$.config, - whole = Math.PI * ($$.hasType('gauge') && !config.gauge_fullCircle ? 1 : 2); - return d ? (d.endAngle - d.startAngle) / whole : null; - }; - - c3_chart_internal_fn.convertToArcData = function (d) { - return this.addName({ - id: d.data.id, - value: d.value, - ratio: this.getArcRatio(d), - index: d.index - }); - }; - - c3_chart_internal_fn.textForArcLabel = function (d) { - var $$ = this, - updated, value, ratio, id, format; - if (! $$.shouldShowArcLabel()) { return ""; } - updated = $$.updateAngle(d); - value = updated ? updated.value : null; - ratio = $$.getArcRatio(updated); - id = d.data.id; - if (! $$.hasType('gauge') && ! $$.meetsArcLabelThreshold(ratio)) { return ""; } - format = $$.getArcLabelFormat(); - return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio); - }; - - c3_chart_internal_fn.expandArc = function (targetIds) { - var $$ = this, interval; - - // MEMO: avoid to cancel transition - if ($$.transiting) { - interval = window.setInterval(function () { - if (!$$.transiting) { - window.clearInterval(interval); - if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) { - $$.expandArc(targetIds); - } - } - }, 10); - return; - } - - targetIds = $$.mapToTargetIds(targetIds); - - $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).each(function (d) { - if (! $$.shouldExpand(d.data.id)) { return; } - $$.d3.select(this).selectAll('path') - .transition().duration($$.expandDuration(d.data.id)) - .attr("d", $$.svgArcExpanded) - .transition().duration($$.expandDuration(d.data.id) * 2) - .attr("d", $$.svgArcExpandedSub) - .each(function (d) { - if ($$.isDonutType(d.data)) { - // callback here - } - }); - }); - }; - - c3_chart_internal_fn.unexpandArc = function (targetIds) { - var $$ = this; - - if ($$.transiting) { return; } - - targetIds = $$.mapToTargetIds(targetIds); - - $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).selectAll('path') - .transition().duration(function(d) { - return $$.expandDuration(d.data.id); - }) - .attr("d", $$.svgArc); - $$.svg.selectAll('.' + CLASS.arc) - .style("opacity", 1); - }; - - c3_chart_internal_fn.expandDuration = function (id) { - var $$ = this, config = $$.config; - - if ($$.isDonutType(id)) { - return config.donut_expand_duration; - } else if ($$.isGaugeType(id)) { - return config.gauge_expand_duration; - } else if ($$.isPieType(id)) { - return config.pie_expand_duration; - } else { - return 50; - } - - }; - - c3_chart_internal_fn.shouldExpand = function (id) { - var $$ = this, config = $$.config; - return ($$.isDonutType(id) && config.donut_expand) || - ($$.isGaugeType(id) && config.gauge_expand) || - ($$.isPieType(id) && config.pie_expand); - }; - - c3_chart_internal_fn.shouldShowArcLabel = function () { - var $$ = this, config = $$.config, shouldShow = true; - if ($$.hasType('donut')) { - shouldShow = config.donut_label_show; - } else if ($$.hasType('pie')) { - shouldShow = config.pie_label_show; - } - // when gauge, always true - return shouldShow; - }; - - c3_chart_internal_fn.meetsArcLabelThreshold = function (ratio) { - var $$ = this, config = $$.config, - threshold = $$.hasType('donut') ? config.donut_label_threshold : config.pie_label_threshold; - return ratio >= threshold; - }; - - c3_chart_internal_fn.getArcLabelFormat = function () { - var $$ = this, config = $$.config, - format = config.pie_label_format; - if ($$.hasType('gauge')) { - format = config.gauge_label_format; - } else if ($$.hasType('donut')) { - format = config.donut_label_format; - } - return format; - }; - - c3_chart_internal_fn.getArcTitle = function () { - var $$ = this; - return $$.hasType('donut') ? $$.config.donut_title : ""; - }; - - c3_chart_internal_fn.updateTargetsForArc = function (targets) { - var $$ = this, main = $$.main, - mainPieUpdate, mainPieEnter, - classChartArc = $$.classChartArc.bind($$), - classArcs = $$.classArcs.bind($$), - classFocus = $$.classFocus.bind($$); - mainPieUpdate = main.select('.' + CLASS.chartArcs).selectAll('.' + CLASS.chartArc) - .data($$.pie(targets)) - .attr("class", function (d) { return classChartArc(d) + classFocus(d.data); }); - mainPieEnter = mainPieUpdate.enter().append("g") - .attr("class", classChartArc); - mainPieEnter.append('g') - .attr('class', classArcs); - mainPieEnter.append("text") - .attr("dy", $$.hasType('gauge') ? "-.1em" : ".35em") - .style("opacity", 0) - .style("text-anchor", "middle") - .style("pointer-events", "none"); - // MEMO: can not keep same color..., but not bad to update color in redraw - //mainPieUpdate.exit().remove(); - }; - - c3_chart_internal_fn.initArc = function () { - var $$ = this; - $$.arcs = $$.main.select('.' + CLASS.chart).append("g") - .attr("class", CLASS.chartArcs) - .attr("transform", $$.getTranslate('arc')); - $$.arcs.append('text') - .attr('class', CLASS.chartArcsTitle) - .style("text-anchor", "middle") - .text($$.getArcTitle()); - }; - - c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransform) { - var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main, - mainArc; - mainArc = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arc) - .data($$.arcData.bind($$)); - mainArc.enter().append('path') - .attr("class", $$.classArc.bind($$)) - .style("fill", function (d) { return $$.color(d.data); }) - .style("cursor", function (d) { return config.interaction_enabled && config.data_selection_isselectable(d) ? "pointer" : null; }) - .style("opacity", 0) - .each(function (d) { - if ($$.isGaugeType(d.data)) { - d.startAngle = d.endAngle = config.gauge_startingAngle; - } - this._current = d; - }); - mainArc - .attr("transform", function (d) { return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : ""; }) - .style("opacity", function (d) { return d === this._current ? 0 : 1; }) - .on('mouseover', config.interaction_enabled ? function (d) { - var updated, arcData; - if ($$.transiting) { // skip while transiting - return; - } - updated = $$.updateAngle(d); - if (updated) { - arcData = $$.convertToArcData(updated); - // transitions - $$.expandArc(updated.data.id); - $$.api.focus(updated.data.id); - $$.toggleFocusLegend(updated.data.id, true); - $$.config.data_onmouseover(arcData, this); - } - } : null) - .on('mousemove', config.interaction_enabled ? function (d) { - var updated = $$.updateAngle(d), arcData, selectedData; - if (updated) { - arcData = $$.convertToArcData(updated), - selectedData = [arcData]; - $$.showTooltip(selectedData, this); - } - } : null) - .on('mouseout', config.interaction_enabled ? function (d) { - var updated, arcData; - if ($$.transiting) { // skip while transiting - return; - } - updated = $$.updateAngle(d); - if (updated) { - arcData = $$.convertToArcData(updated); - // transitions - $$.unexpandArc(updated.data.id); - $$.api.revert(); - $$.revertLegend(); - $$.hideTooltip(); - $$.config.data_onmouseout(arcData, this); - } - } : null) - .on('click', config.interaction_enabled ? function (d, i) { - var updated = $$.updateAngle(d), arcData; - if (updated) { - arcData = $$.convertToArcData(updated); - if ($$.toggleShape) { - $$.toggleShape(this, arcData, i); - } - $$.config.data_onclick.call($$.api, arcData, this); - } - } : null) - .each(function () { $$.transiting = true; }) - .transition().duration(duration) - .attrTween("d", function (d) { - var updated = $$.updateAngle(d), interpolate; - if (! updated) { - return function () { return "M 0 0"; }; - } - // if (this._current === d) { - // this._current = { - // startAngle: Math.PI*2, - // endAngle: Math.PI*2, - // }; - // } - if (isNaN(this._current.startAngle)) { - this._current.startAngle = 0; - } - if (isNaN(this._current.endAngle)) { - this._current.endAngle = this._current.startAngle; - } - interpolate = d3.interpolate(this._current, updated); - this._current = interpolate(0); - return function (t) { - var interpolated = interpolate(t); - interpolated.data = d.data; // data.id will be updated by interporator - return $$.getArc(interpolated, true); - }; - }) - .attr("transform", withTransform ? "scale(1)" : "") - .style("fill", function (d) { - return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id); - }) // Where gauge reading color would receive customization. - .style("opacity", 1) - .call($$.endall, function () { - $$.transiting = false; - }); - mainArc.exit().transition().duration(durationForExit) - .style('opacity', 0) - .remove(); - main.selectAll('.' + CLASS.chartArc).select('text') - .style("opacity", 0) - .attr('class', function (d) { return $$.isGaugeType(d.data) ? CLASS.gaugeValue : ''; }) - .text($$.textForArcLabel.bind($$)) - .attr("transform", $$.transformForArcLabel.bind($$)) - .style('font-size', function (d) { return $$.isGaugeType(d.data) ? Math.round($$.radius / 5) + 'px' : ''; }) - .transition().duration(duration) - .style("opacity", function (d) { return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0; }); - main.select('.' + CLASS.chartArcsTitle) - .style("opacity", $$.hasType('donut') || $$.hasType('gauge') ? 1 : 0); - - if ($$.hasType('gauge')) { - $$.arcs.select('.' + CLASS.chartArcsBackground) - .attr("d", function () { - var d = { - data: [{value: config.gauge_max}], - startAngle: config.gauge_startingAngle, - endAngle: -1 * config.gauge_startingAngle - }; - return $$.getArc(d, true, true); - }); - $$.arcs.select('.' + CLASS.chartArcsGaugeUnit) - .attr("dy", ".75em") - .text(config.gauge_label_show ? config.gauge_units : ''); - $$.arcs.select('.' + CLASS.chartArcsGaugeMin) - .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2))) + "px") - .attr("dy", "1.2em") - .text(config.gauge_label_show ? config.gauge_min : ''); - $$.arcs.select('.' + CLASS.chartArcsGaugeMax) - .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) + "px") - .attr("dy", "1.2em") - .text(config.gauge_label_show ? config.gauge_max : ''); - } - }; - c3_chart_internal_fn.initGauge = function () { - var arcs = this.arcs; - if (this.hasType('gauge')) { - arcs.append('path') - .attr("class", CLASS.chartArcsBackground); - arcs.append("text") - .attr("class", CLASS.chartArcsGaugeUnit) - .style("text-anchor", "middle") - .style("pointer-events", "none"); - arcs.append("text") - .attr("class", CLASS.chartArcsGaugeMin) - .style("text-anchor", "middle") - .style("pointer-events", "none"); - arcs.append("text") - .attr("class", CLASS.chartArcsGaugeMax) - .style("text-anchor", "middle") - .style("pointer-events", "none"); - } - }; - c3_chart_internal_fn.getGaugeLabelHeight = function () { - return this.config.gauge_label_show ? 20 : 0; - }; - - c3_chart_internal_fn.initRegion = function () { - var $$ = this; - $$.region = $$.main.append('g') - .attr("clip-path", $$.clipPath) - .attr("class", CLASS.regions); - }; - c3_chart_internal_fn.updateRegion = function (duration) { - var $$ = this, config = $$.config; - - // hide if arc type - $$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible'); - - $$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region) - .data(config.regions); - $$.mainRegion.enter().append('g') - .append('rect') - .style("fill-opacity", 0); - $$.mainRegion - .attr('class', $$.classRegion.bind($$)); - $$.mainRegion.exit().transition().duration(duration) - .style("opacity", 0) - .remove(); - }; - c3_chart_internal_fn.redrawRegion = function (withTransition) { - var $$ = this, - regions = $$.mainRegion.selectAll('rect').each(function () { - // data is binded to g and it's not transferred to rect (child node) automatically, - // then data of each rect has to be updated manually. - // TODO: there should be more efficient way to solve this? - var parentData = $$.d3.select(this.parentNode).datum(); - $$.d3.select(this).datum(parentData); - }), - x = $$.regionX.bind($$), - y = $$.regionY.bind($$), - w = $$.regionWidth.bind($$), - h = $$.regionHeight.bind($$); - return [ - (withTransition ? regions.transition() : regions) - .attr("x", x) - .attr("y", y) - .attr("width", w) - .attr("height", h) - .style("fill-opacity", function (d) { return isValue(d.opacity) ? d.opacity : 0.1; }) - ]; - }; - c3_chart_internal_fn.regionX = function (d) { - var $$ = this, config = $$.config, - xPos, yScale = d.axis === 'y' ? $$.y : $$.y2; - if (d.axis === 'y' || d.axis === 'y2') { - xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0; - } else { - xPos = config.axis_rotated ? 0 : ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0); - } - return xPos; - }; - c3_chart_internal_fn.regionY = function (d) { - var $$ = this, config = $$.config, - yPos, yScale = d.axis === 'y' ? $$.y : $$.y2; - if (d.axis === 'y' || d.axis === 'y2') { - yPos = config.axis_rotated ? 0 : ('end' in d ? yScale(d.end) : 0); - } else { - yPos = config.axis_rotated ? ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0) : 0; - } - return yPos; - }; - c3_chart_internal_fn.regionWidth = function (d) { - var $$ = this, config = $$.config, - start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2; - if (d.axis === 'y' || d.axis === 'y2') { - end = config.axis_rotated ? ('end' in d ? yScale(d.end) : $$.width) : $$.width; - } else { - end = config.axis_rotated ? $$.width : ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width); - } - return end < start ? 0 : end - start; - }; - c3_chart_internal_fn.regionHeight = function (d) { - var $$ = this, config = $$.config, - start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2; - if (d.axis === 'y' || d.axis === 'y2') { - end = config.axis_rotated ? $$.height : ('start' in d ? yScale(d.start) : $$.height); - } else { - end = config.axis_rotated ? ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height) : $$.height; - } - return end < start ? 0 : end - start; - }; - c3_chart_internal_fn.isRegionOnX = function (d) { - return !d.axis || d.axis === 'x'; - }; - - c3_chart_internal_fn.drag = function (mouse) { - var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3; - var sx, sy, mx, my, minX, maxX, minY, maxY; - - if ($$.hasArcType()) { return; } - if (! config.data_selection_enabled) { return; } // do nothing if not selectable - if (config.zoom_enabled && ! $$.zoom.altDomain) { return; } // skip if zoomable because of conflict drag dehavior - if (!config.data_selection_multiple) { return; } // skip when single selection because drag is used for multiple selection - - sx = $$.dragStart[0]; - sy = $$.dragStart[1]; - mx = mouse[0]; - my = mouse[1]; - minX = Math.min(sx, mx); - maxX = Math.max(sx, mx); - minY = (config.data_selection_grouped) ? $$.margin.top : Math.min(sy, my); - maxY = (config.data_selection_grouped) ? $$.height : Math.max(sy, my); - - main.select('.' + CLASS.dragarea) - .attr('x', minX) - .attr('y', minY) - .attr('width', maxX - minX) - .attr('height', maxY - minY); - // TODO: binary search when multiple xs - main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape) - .filter(function (d) { return config.data_selection_isselectable(d); }) - .each(function (d, i) { - var shape = d3.select(this), - isSelected = shape.classed(CLASS.SELECTED), - isIncluded = shape.classed(CLASS.INCLUDED), - _x, _y, _w, _h, toggle, isWithin = false, box; - if (shape.classed(CLASS.circle)) { - _x = shape.attr("cx") * 1; - _y = shape.attr("cy") * 1; - toggle = $$.togglePoint; - isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY; - } - else if (shape.classed(CLASS.bar)) { - box = getPathBox(this); - _x = box.x; - _y = box.y; - _w = box.width; - _h = box.height; - toggle = $$.togglePath; - isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY); - } else { - // line/area selection not supported yet - return; - } - if (isWithin ^ isIncluded) { - shape.classed(CLASS.INCLUDED, !isIncluded); - // TODO: included/unincluded callback here - shape.classed(CLASS.SELECTED, !isSelected); - toggle.call($$, !isSelected, shape, d, i); - } - }); - }; - - c3_chart_internal_fn.dragstart = function (mouse) { - var $$ = this, config = $$.config; - if ($$.hasArcType()) { return; } - if (! config.data_selection_enabled) { return; } // do nothing if not selectable - $$.dragStart = mouse; - $$.main.select('.' + CLASS.chart).append('rect') - .attr('class', CLASS.dragarea) - .style('opacity', 0.1); - $$.dragging = true; - }; - - c3_chart_internal_fn.dragend = function () { - var $$ = this, config = $$.config; - if ($$.hasArcType()) { return; } - if (! config.data_selection_enabled) { return; } // do nothing if not selectable - $$.main.select('.' + CLASS.dragarea) - .transition().duration(100) - .style('opacity', 0) - .remove(); - $$.main.selectAll('.' + CLASS.shape) - .classed(CLASS.INCLUDED, false); - $$.dragging = false; - }; - - c3_chart_internal_fn.selectPoint = function (target, d, i) { - var $$ = this, config = $$.config, - cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$), - cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$), - r = $$.pointSelectR.bind($$); - config.data_onselected.call($$.api, d, target.node()); - // add selected-circle on low layer g - $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i) - .data([d]) - .enter().append('circle') - .attr("class", function () { return $$.generateClass(CLASS.selectedCircle, i); }) - .attr("cx", cx) - .attr("cy", cy) - .attr("stroke", function () { return $$.color(d); }) - .attr("r", function (d) { return $$.pointSelectR(d) * 1.4; }) - .transition().duration(100) - .attr("r", r); - }; - c3_chart_internal_fn.unselectPoint = function (target, d, i) { - var $$ = this; - $$.config.data_onunselected.call($$.api, d, target.node()); - // remove selected-circle from low layer g - $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i) - .transition().duration(100).attr('r', 0) - .remove(); - }; - c3_chart_internal_fn.togglePoint = function (selected, target, d, i) { - selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i); - }; - c3_chart_internal_fn.selectPath = function (target, d) { - var $$ = this; - $$.config.data_onselected.call($$, d, target.node()); - if ($$.config.interaction_brighten) { - target.transition().duration(100) - .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); }); - } - }; - c3_chart_internal_fn.unselectPath = function (target, d) { - var $$ = this; - $$.config.data_onunselected.call($$, d, target.node()); - if ($$.config.interaction_brighten) { - target.transition().duration(100) - .style("fill", function () { return $$.color(d); }); - } - }; - c3_chart_internal_fn.togglePath = function (selected, target, d, i) { - selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i); - }; - c3_chart_internal_fn.getToggle = function (that, d) { - var $$ = this, toggle; - if (that.nodeName === 'circle') { - if ($$.isStepType(d)) { - // circle is hidden in step chart, so treat as within the click area - toggle = function () {}; // TODO: how to select step chart? - } else { - toggle = $$.togglePoint; - } - } - else if (that.nodeName === 'path') { - toggle = $$.togglePath; - } - return toggle; - }; - c3_chart_internal_fn.toggleShape = function (that, d, i) { - var $$ = this, d3 = $$.d3, config = $$.config, - shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED), - toggle = $$.getToggle(that, d).bind($$); - - if (config.data_selection_enabled && config.data_selection_isselectable(d)) { - if (!config.data_selection_multiple) { - $$.main.selectAll('.' + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : "")).selectAll('.' + CLASS.shape).each(function (d, i) { - var shape = d3.select(this); - if (shape.classed(CLASS.SELECTED)) { toggle(false, shape.classed(CLASS.SELECTED, false), d, i); } - }); - } - shape.classed(CLASS.SELECTED, !isSelected); - toggle(!isSelected, shape, d, i); - } - }; - - c3_chart_internal_fn.initBrush = function () { - var $$ = this, d3 = $$.d3; - $$.brush = d3.svg.brush().on("brush", function () { $$.redrawForBrush(); }); - $$.brush.update = function () { - if ($$.context) { $$.context.select('.' + CLASS.brush).call(this); } - return this; - }; - $$.brush.scale = function (scale) { - return $$.config.axis_rotated ? this.y(scale) : this.x(scale); - }; - }; - c3_chart_internal_fn.initSubchart = function () { - var $$ = this, config = $$.config, - context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context')), - visibility = config.subchart_show ? 'visible' : 'hidden'; - - context.style('visibility', visibility); - - // Define g for chart area - context.append('g') - .attr("clip-path", $$.clipPathForSubchart) - .attr('class', CLASS.chart); - - // Define g for bar chart area - context.select('.' + CLASS.chart).append("g") - .attr("class", CLASS.chartBars); - - // Define g for line chart area - context.select('.' + CLASS.chart).append("g") - .attr("class", CLASS.chartLines); - - // Add extent rect for Brush - context.append("g") - .attr("clip-path", $$.clipPath) - .attr("class", CLASS.brush) - .call($$.brush); - - // ATTENTION: This must be called AFTER chart added - // Add Axis - $$.axes.subx = context.append("g") - .attr("class", CLASS.axisX) - .attr("transform", $$.getTranslate('subx')) - .attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis) - .style("visibility", config.subchart_axis_x_show ? visibility : 'hidden'); - }; - c3_chart_internal_fn.updateTargetsForSubchart = function (targets) { - var $$ = this, context = $$.context, config = $$.config, - contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate, - classChartBar = $$.classChartBar.bind($$), - classBars = $$.classBars.bind($$), - classChartLine = $$.classChartLine.bind($$), - classLines = $$.classLines.bind($$), - classAreas = $$.classAreas.bind($$); - - if (config.subchart_show) { - //-- Bar --// - contextBarUpdate = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar) - .data(targets) - .attr('class', classChartBar); - contextBarEnter = contextBarUpdate.enter().append('g') - .style('opacity', 0) - .attr('class', classChartBar); - // Bars for each data - contextBarEnter.append('g') - .attr("class", classBars); - - //-- Line --// - contextLineUpdate = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine) - .data(targets) - .attr('class', classChartLine); - contextLineEnter = contextLineUpdate.enter().append('g') - .style('opacity', 0) - .attr('class', classChartLine); - // Lines for each data - contextLineEnter.append("g") - .attr("class", classLines); - // Area - contextLineEnter.append("g") - .attr("class", classAreas); - - //-- Brush --// - context.selectAll('.' + CLASS.brush + ' rect') - .attr(config.axis_rotated ? "width" : "height", config.axis_rotated ? $$.width2 : $$.height2); - } - }; - c3_chart_internal_fn.updateBarForSubchart = function (durationForExit) { - var $$ = this; - $$.contextBar = $$.context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar) - .data($$.barData.bind($$)); - $$.contextBar.enter().append('path') - .attr("class", $$.classBar.bind($$)) - .style("stroke", 'none') - .style("fill", $$.color); - $$.contextBar - .style("opacity", $$.initialOpacity.bind($$)); - $$.contextBar.exit().transition().duration(durationForExit) - .style('opacity', 0) - .remove(); - }; - c3_chart_internal_fn.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) { - (withTransition ? this.contextBar.transition(Math.random().toString()).duration(duration) : this.contextBar) - .attr('d', drawBarOnSub) - .style('opacity', 1); - }; - c3_chart_internal_fn.updateLineForSubchart = function (durationForExit) { - var $$ = this; - $$.contextLine = $$.context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line) - .data($$.lineData.bind($$)); - $$.contextLine.enter().append('path') - .attr('class', $$.classLine.bind($$)) - .style('stroke', $$.color); - $$.contextLine - .style("opacity", $$.initialOpacity.bind($$)); - $$.contextLine.exit().transition().duration(durationForExit) - .style('opacity', 0) - .remove(); - }; - c3_chart_internal_fn.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) { - (withTransition ? this.contextLine.transition(Math.random().toString()).duration(duration) : this.contextLine) - .attr("d", drawLineOnSub) - .style('opacity', 1); - }; - c3_chart_internal_fn.updateAreaForSubchart = function (durationForExit) { - var $$ = this, d3 = $$.d3; - $$.contextArea = $$.context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area) - .data($$.lineData.bind($$)); - $$.contextArea.enter().append('path') - .attr("class", $$.classArea.bind($$)) - .style("fill", $$.color) - .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; }); - $$.contextArea - .style("opacity", 0); - $$.contextArea.exit().transition().duration(durationForExit) - .style('opacity', 0) - .remove(); - }; - c3_chart_internal_fn.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) { - (withTransition ? this.contextArea.transition(Math.random().toString()).duration(duration) : this.contextArea) - .attr("d", drawAreaOnSub) - .style("fill", this.color) - .style("opacity", this.orgAreaOpacity); - }; - c3_chart_internal_fn.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) { - var $$ = this, d3 = $$.d3, config = $$.config, - drawAreaOnSub, drawBarOnSub, drawLineOnSub; - - $$.context.style('visibility', config.subchart_show ? 'visible' : 'hidden'); - - // subchart - if (config.subchart_show) { - // reflect main chart to extent on subchart if zoomed - if (d3.event && d3.event.type === 'zoom') { - $$.brush.extent($$.x.orgDomain()).update(); - } - // update subchart elements if needed - if (withSubchart) { - - // extent rect - if (!$$.brush.empty()) { - $$.brush.extent($$.x.orgDomain()).update(); - } - // setup drawer - MEMO: this must be called after axis updated - drawAreaOnSub = $$.generateDrawArea(areaIndices, true); - drawBarOnSub = $$.generateDrawBar(barIndices, true); - drawLineOnSub = $$.generateDrawLine(lineIndices, true); - - $$.updateBarForSubchart(duration); - $$.updateLineForSubchart(duration); - $$.updateAreaForSubchart(duration); - - $$.redrawBarForSubchart(drawBarOnSub, duration, duration); - $$.redrawLineForSubchart(drawLineOnSub, duration, duration); - $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration); - } - } - }; - c3_chart_internal_fn.redrawForBrush = function () { - var $$ = this, x = $$.x; - $$.redraw({ - withTransition: false, - withY: $$.config.zoom_rescale, - withSubchart: false, - withUpdateXDomain: true, - withDimension: false - }); - $$.config.subchart_onbrush.call($$.api, x.orgDomain()); - }; - c3_chart_internal_fn.transformContext = function (withTransition, transitions) { - var $$ = this, subXAxis; - if (transitions && transitions.axisSubX) { - subXAxis = transitions.axisSubX; - } else { - subXAxis = $$.context.select('.' + CLASS.axisX); - if (withTransition) { subXAxis = subXAxis.transition(); } - } - $$.context.attr("transform", $$.getTranslate('context')); - subXAxis.attr("transform", $$.getTranslate('subx')); - }; - c3_chart_internal_fn.getDefaultExtent = function () { - var $$ = this, config = $$.config, - extent = isFunction(config.axis_x_extent) ? config.axis_x_extent($$.getXDomain($$.data.targets)) : config.axis_x_extent; - if ($$.isTimeSeries()) { - extent = [$$.parseDate(extent[0]), $$.parseDate(extent[1])]; - } - return extent; - }; - - c3_chart_internal_fn.initZoom = function () { - var $$ = this, d3 = $$.d3, config = $$.config, startEvent; - - $$.zoom = d3.behavior.zoom() - .on("zoomstart", function () { - startEvent = d3.event.sourceEvent; - $$.zoom.altDomain = d3.event.sourceEvent.altKey ? $$.x.orgDomain() : null; - config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent); - }) - .on("zoom", function () { - $$.redrawForZoom.call($$); - }) - .on('zoomend', function () { - var event = d3.event.sourceEvent; - // if click, do nothing. otherwise, click interaction will be canceled. - if (event && startEvent.clientX === event.clientX && startEvent.clientY === event.clientY) { - return; - } - $$.redrawEventRect(); - $$.updateZoom(); - config.zoom_onzoomend.call($$.api, $$.x.orgDomain()); - }); - $$.zoom.scale = function (scale) { - return config.axis_rotated ? this.y(scale) : this.x(scale); - }; - $$.zoom.orgScaleExtent = function () { - var extent = config.zoom_extent ? config.zoom_extent : [1, 10]; - return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])]; - }; - $$.zoom.updateScaleExtent = function () { - var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.getZoomDomain()), - extent = this.orgScaleExtent(); - this.scaleExtent([extent[0] * ratio, extent[1] * ratio]); - return this; - }; - }; - c3_chart_internal_fn.getZoomDomain = function () { - var $$ = this, config = $$.config, d3 = $$.d3, - min = d3.min([$$.orgXDomain[0], config.zoom_x_min]), - max = d3.max([$$.orgXDomain[1], config.zoom_x_max]); - return [min, max]; - }; - c3_chart_internal_fn.updateZoom = function () { - var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function () {}; - $$.main.select('.' + CLASS.zoomRect).call(z).on("dblclick.zoom", null); - $$.main.selectAll('.' + CLASS.eventRect).call(z).on("dblclick.zoom", null); - }; - c3_chart_internal_fn.redrawForZoom = function () { - var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x; - if (!config.zoom_enabled) { - return; - } - if ($$.filterTargetsToShow($$.data.targets).length === 0) { - return; - } - if (d3.event.sourceEvent.type === 'mousemove' && zoom.altDomain) { - x.domain(zoom.altDomain); - zoom.scale(x).updateScaleExtent(); - return; - } - if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) { - x.domain([$$.orgXDomain[0] - 1e-10, x.orgDomain()[1]]); - } - $$.redraw({ - withTransition: false, - withY: config.zoom_rescale, - withSubchart: false, - withEventRect: false, - withDimension: false - }); - if (d3.event.sourceEvent.type === 'mousemove') { - $$.cancelClick = true; - } - config.zoom_onzoom.call($$.api, x.orgDomain()); - }; - - c3_chart_internal_fn.generateColor = function () { - var $$ = this, config = $$.config, d3 = $$.d3, - colors = config.data_colors, - pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.scale.category10().range(), - callback = config.data_color, - ids = []; - - return function (d) { - var id = d.id || (d.data && d.data.id) || d, color; - - // if callback function is provided - if (colors[id] instanceof Function) { - color = colors[id](d); - } - // if specified, choose that color - else if (colors[id]) { - color = colors[id]; - } - // if not specified, choose from pattern - else { - if (ids.indexOf(id) < 0) { ids.push(id); } - color = pattern[ids.indexOf(id) % pattern.length]; - colors[id] = color; - } - return callback instanceof Function ? callback(color, d) : color; - }; - }; - c3_chart_internal_fn.generateLevelColor = function () { - var $$ = this, config = $$.config, - colors = config.color_pattern, - threshold = config.color_threshold, - asValue = threshold.unit === 'value', - values = threshold.values && threshold.values.length ? threshold.values : [], - max = threshold.max || 100; - return notEmpty(config.color_threshold) ? function (value) { - var i, v, color = colors[colors.length - 1]; - for (i = 0; i < values.length; i++) { - v = asValue ? value : (value * 100 / max); - if (v < values[i]) { - color = colors[i]; - break; - } - } - return color; - } : null; - }; - - c3_chart_internal_fn.getYFormat = function (forArc) { - var $$ = this, - formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat, - formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format; - return function (v, ratio, id) { - var format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY; - return format.call($$, v, ratio); - }; - }; - c3_chart_internal_fn.yFormat = function (v) { - var $$ = this, config = $$.config, - format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat; - return format(v); - }; - c3_chart_internal_fn.y2Format = function (v) { - var $$ = this, config = $$.config, - format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat; - return format(v); - }; - c3_chart_internal_fn.defaultValueFormat = function (v) { - return isValue(v) ? +v : ""; - }; - c3_chart_internal_fn.defaultArcValueFormat = function (v, ratio) { - return (ratio * 100).toFixed(1) + '%'; - }; - c3_chart_internal_fn.dataLabelFormat = function (targetId) { - var $$ = this, data_labels = $$.config.data_labels, - format, defaultFormat = function (v) { return isValue(v) ? +v : ""; }; - // find format according to axis id - if (typeof data_labels.format === 'function') { - format = data_labels.format; - } else if (typeof data_labels.format === 'object') { - if (data_labels.format[targetId]) { - format = data_labels.format[targetId] === true ? defaultFormat : data_labels.format[targetId]; - } else { - format = function () { return ''; }; - } - } else { - format = defaultFormat; - } - return format; - }; - - c3_chart_internal_fn.hasCaches = function (ids) { - for (var i = 0; i < ids.length; i++) { - if (! (ids[i] in this.cache)) { return false; } - } - return true; - }; - c3_chart_internal_fn.addCache = function (id, target) { - this.cache[id] = this.cloneTarget(target); - }; - c3_chart_internal_fn.getCaches = function (ids) { - var targets = [], i; - for (i = 0; i < ids.length; i++) { - if (ids[i] in this.cache) { targets.push(this.cloneTarget(this.cache[ids[i]])); } - } - return targets; - }; - - var CLASS = c3_chart_internal_fn.CLASS = { - target: 'c3-target', - chart: 'c3-chart', - chartLine: 'c3-chart-line', - chartLines: 'c3-chart-lines', - chartBar: 'c3-chart-bar', - chartBars: 'c3-chart-bars', - chartText: 'c3-chart-text', - chartTexts: 'c3-chart-texts', - chartArc: 'c3-chart-arc', - chartArcs: 'c3-chart-arcs', - chartArcsTitle: 'c3-chart-arcs-title', - chartArcsBackground: 'c3-chart-arcs-background', - chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit', - chartArcsGaugeMax: 'c3-chart-arcs-gauge-max', - chartArcsGaugeMin: 'c3-chart-arcs-gauge-min', - selectedCircle: 'c3-selected-circle', - selectedCircles: 'c3-selected-circles', - eventRect: 'c3-event-rect', - eventRects: 'c3-event-rects', - eventRectsSingle: 'c3-event-rects-single', - eventRectsMultiple: 'c3-event-rects-multiple', - zoomRect: 'c3-zoom-rect', - brush: 'c3-brush', - focused: 'c3-focused', - defocused: 'c3-defocused', - region: 'c3-region', - regions: 'c3-regions', - title: 'c3-title', - tooltipContainer: 'c3-tooltip-container', - tooltip: 'c3-tooltip', - tooltipName: 'c3-tooltip-name', - shape: 'c3-shape', - shapes: 'c3-shapes', - line: 'c3-line', - lines: 'c3-lines', - bar: 'c3-bar', - bars: 'c3-bars', - circle: 'c3-circle', - circles: 'c3-circles', - arc: 'c3-arc', - arcs: 'c3-arcs', - area: 'c3-area', - areas: 'c3-areas', - empty: 'c3-empty', - text: 'c3-text', - texts: 'c3-texts', - gaugeValue: 'c3-gauge-value', - grid: 'c3-grid', - gridLines: 'c3-grid-lines', - xgrid: 'c3-xgrid', - xgrids: 'c3-xgrids', - xgridLine: 'c3-xgrid-line', - xgridLines: 'c3-xgrid-lines', - xgridFocus: 'c3-xgrid-focus', - ygrid: 'c3-ygrid', - ygrids: 'c3-ygrids', - ygridLine: 'c3-ygrid-line', - ygridLines: 'c3-ygrid-lines', - axis: 'c3-axis', - axisX: 'c3-axis-x', - axisXLabel: 'c3-axis-x-label', - axisY: 'c3-axis-y', - axisYLabel: 'c3-axis-y-label', - axisY2: 'c3-axis-y2', - axisY2Label: 'c3-axis-y2-label', - legendBackground: 'c3-legend-background', - legendItem: 'c3-legend-item', - legendItemEvent: 'c3-legend-item-event', - legendItemTile: 'c3-legend-item-tile', - legendItemHidden: 'c3-legend-item-hidden', - legendItemFocused: 'c3-legend-item-focused', - dragarea: 'c3-dragarea', - EXPANDED: '_expanded_', - SELECTED: '_selected_', - INCLUDED: '_included_' - }; - c3_chart_internal_fn.generateClass = function (prefix, targetId) { - return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId); - }; - c3_chart_internal_fn.classText = function (d) { - return this.generateClass(CLASS.text, d.index); - }; - c3_chart_internal_fn.classTexts = function (d) { - return this.generateClass(CLASS.texts, d.id); - }; - c3_chart_internal_fn.classShape = function (d) { - return this.generateClass(CLASS.shape, d.index); - }; - c3_chart_internal_fn.classShapes = function (d) { - return this.generateClass(CLASS.shapes, d.id); - }; - c3_chart_internal_fn.classLine = function (d) { - return this.classShape(d) + this.generateClass(CLASS.line, d.id); - }; - c3_chart_internal_fn.classLines = function (d) { - return this.classShapes(d) + this.generateClass(CLASS.lines, d.id); - }; - c3_chart_internal_fn.classCircle = function (d) { - return this.classShape(d) + this.generateClass(CLASS.circle, d.index); - }; - c3_chart_internal_fn.classCircles = function (d) { - return this.classShapes(d) + this.generateClass(CLASS.circles, d.id); - }; - c3_chart_internal_fn.classBar = function (d) { - return this.classShape(d) + this.generateClass(CLASS.bar, d.index); - }; - c3_chart_internal_fn.classBars = function (d) { - return this.classShapes(d) + this.generateClass(CLASS.bars, d.id); - }; - c3_chart_internal_fn.classArc = function (d) { - return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id); - }; - c3_chart_internal_fn.classArcs = function (d) { - return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id); - }; - c3_chart_internal_fn.classArea = function (d) { - return this.classShape(d) + this.generateClass(CLASS.area, d.id); - }; - c3_chart_internal_fn.classAreas = function (d) { - return this.classShapes(d) + this.generateClass(CLASS.areas, d.id); - }; - c3_chart_internal_fn.classRegion = function (d, i) { - return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : ''); - }; - c3_chart_internal_fn.classEvent = function (d) { - return this.generateClass(CLASS.eventRect, d.index); - }; - c3_chart_internal_fn.classTarget = function (id) { - var $$ = this; - var additionalClassSuffix = $$.config.data_classes[id], additionalClass = ''; - if (additionalClassSuffix) { - additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix; - } - return $$.generateClass(CLASS.target, id) + additionalClass; - }; - c3_chart_internal_fn.classFocus = function (d) { - return this.classFocused(d) + this.classDefocused(d); - }; - c3_chart_internal_fn.classFocused = function (d) { - return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : ''); - }; - c3_chart_internal_fn.classDefocused = function (d) { - return ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : ''); - }; - c3_chart_internal_fn.classChartText = function (d) { - return CLASS.chartText + this.classTarget(d.id); - }; - c3_chart_internal_fn.classChartLine = function (d) { - return CLASS.chartLine + this.classTarget(d.id); - }; - c3_chart_internal_fn.classChartBar = function (d) { - return CLASS.chartBar + this.classTarget(d.id); - }; - c3_chart_internal_fn.classChartArc = function (d) { - return CLASS.chartArc + this.classTarget(d.data.id); - }; - c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) { - return targetId || targetId === 0 ? ('-' + targetId).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g, '-') : ''; - }; - c3_chart_internal_fn.selectorTarget = function (id, prefix) { - return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id); - }; - c3_chart_internal_fn.selectorTargets = function (ids, prefix) { - var $$ = this; - ids = ids || []; - return ids.length ? ids.map(function (id) { return $$.selectorTarget(id, prefix); }) : null; - }; - c3_chart_internal_fn.selectorLegend = function (id) { - return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id); - }; - c3_chart_internal_fn.selectorLegends = function (ids) { - var $$ = this; - return ids && ids.length ? ids.map(function (id) { return $$.selectorLegend(id); }) : null; - }; - - var isValue = c3_chart_internal_fn.isValue = function (v) { - return v || v === 0; - }, - isFunction = c3_chart_internal_fn.isFunction = function (o) { - return typeof o === 'function'; - }, - isString = c3_chart_internal_fn.isString = function (o) { - return typeof o === 'string'; - }, - isUndefined = c3_chart_internal_fn.isUndefined = function (v) { - return typeof v === 'undefined'; - }, - isDefined = c3_chart_internal_fn.isDefined = function (v) { - return typeof v !== 'undefined'; - }, - ceil10 = c3_chart_internal_fn.ceil10 = function (v) { - return Math.ceil(v / 10) * 10; - }, - asHalfPixel = c3_chart_internal_fn.asHalfPixel = function (n) { - return Math.ceil(n) + 0.5; - }, - diffDomain = c3_chart_internal_fn.diffDomain = function (d) { - return d[1] - d[0]; - }, - isEmpty = c3_chart_internal_fn.isEmpty = function (o) { - return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0); - }, - notEmpty = c3_chart_internal_fn.notEmpty = function (o) { - return !c3_chart_internal_fn.isEmpty(o); - }, - getOption = c3_chart_internal_fn.getOption = function (options, key, defaultValue) { - return isDefined(options[key]) ? options[key] : defaultValue; - }, - hasValue = c3_chart_internal_fn.hasValue = function (dict, value) { - var found = false; - Object.keys(dict).forEach(function (key) { - if (dict[key] === value) { found = true; } - }); - return found; - }, - sanitise = c3_chart_internal_fn.sanitise = function (str) { - return typeof str === 'string' ? str.replace(//g, '>') : str; - }, - getPathBox = c3_chart_internal_fn.getPathBox = function (path) { - var box = path.getBoundingClientRect(), - items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)], - minX = items[0].x, minY = Math.min(items[0].y, items[1].y); - return {x: minX, y: minY, width: box.width, height: box.height}; - }; - - c3_chart_fn.focus = function (targetIds) { - var $$ = this.internal, candidates; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), - - this.revert(); - this.defocus(); - candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false); - if ($$.hasArcType()) { - $$.expandArc(targetIds); - } - $$.toggleFocusLegend(targetIds, true); - - $$.focusedTargetIds = targetIds; - $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) { - return targetIds.indexOf(id) < 0; - }); - }; - - c3_chart_fn.defocus = function (targetIds) { - var $$ = this.internal, candidates; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), - - candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true); - if ($$.hasArcType()) { - $$.unexpandArc(targetIds); - } - $$.toggleFocusLegend(targetIds, false); - - $$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) { - return targetIds.indexOf(id) < 0; - }); - $$.defocusedTargetIds = targetIds; - }; - - c3_chart_fn.revert = function (targetIds) { - var $$ = this.internal, candidates; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets - - candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false); - if ($$.hasArcType()) { - $$.unexpandArc(targetIds); - } - if ($$.config.legend_show) { - $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$))); - $$.legend.selectAll($$.selectorLegends(targetIds)) - .filter(function () { - return $$.d3.select(this).classed(CLASS.legendItemFocused); - }) - .classed(CLASS.legendItemFocused, false); - } - - $$.focusedTargetIds = []; - $$.defocusedTargetIds = []; - }; - - c3_chart_fn.show = function (targetIds, options) { - var $$ = this.internal, targets; - - targetIds = $$.mapToTargetIds(targetIds); - options = options || {}; - - $$.removeHiddenTargetIds(targetIds); - targets = $$.svg.selectAll($$.selectorTargets(targetIds)); - - targets.transition() - .style('opacity', 1, 'important') - .call($$.endall, function () { - targets.style('opacity', null).style('opacity', 1); - }); - - if (options.withLegend) { - $$.showLegend(targetIds); - } - - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); - }; - - c3_chart_fn.hide = function (targetIds, options) { - var $$ = this.internal, targets; - - targetIds = $$.mapToTargetIds(targetIds); - options = options || {}; - - $$.addHiddenTargetIds(targetIds); - targets = $$.svg.selectAll($$.selectorTargets(targetIds)); - - targets.transition() - .style('opacity', 0, 'important') - .call($$.endall, function () { - targets.style('opacity', null).style('opacity', 0); - }); - - if (options.withLegend) { - $$.hideLegend(targetIds); - } - - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); - }; - - c3_chart_fn.toggle = function (targetIds, options) { - var that = this, $$ = this.internal; - $$.mapToTargetIds(targetIds).forEach(function (targetId) { - $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options); - }); - }; - - c3_chart_fn.zoom = function (domain) { - var $$ = this.internal; - if (domain) { - if ($$.isTimeSeries()) { - domain = domain.map(function (x) { return $$.parseDate(x); }); - } - $$.brush.extent(domain); - $$.redraw({withUpdateXDomain: true, withY: $$.config.zoom_rescale}); - $$.config.zoom_onzoom.call(this, $$.x.orgDomain()); - } - return $$.brush.extent(); - }; - c3_chart_fn.zoom.enable = function (enabled) { - var $$ = this.internal; - $$.config.zoom_enabled = enabled; - $$.updateAndRedraw(); - }; - c3_chart_fn.unzoom = function () { - var $$ = this.internal; - $$.brush.clear().update(); - $$.redraw({withUpdateXDomain: true}); - }; - - c3_chart_fn.zoom.max = function (max) { - var $$ = this.internal, config = $$.config, d3 = $$.d3; - if (max === 0 || max) { - config.zoom_x_max = d3.max([$$.orgXDomain[1], max]); - } - else { - return config.zoom_x_max; - } - }; - - c3_chart_fn.zoom.min = function (min) { - var $$ = this.internal, config = $$.config, d3 = $$.d3; - if (min === 0 || min) { - config.zoom_x_min = d3.min([$$.orgXDomain[0], min]); - } - else { - return config.zoom_x_min; - } - }; - - c3_chart_fn.zoom.range = function (range) { - if (arguments.length) { - if (isDefined(range.max)) { this.domain.max(range.max); } - if (isDefined(range.min)) { this.domain.min(range.min); } - } else { - return { - max: this.domain.max(), - min: this.domain.min() - }; - } - }; - - c3_chart_fn.load = function (args) { - var $$ = this.internal, config = $$.config; - // update xs if specified - if (args.xs) { - $$.addXs(args.xs); - } - // update names if exists - if ('names' in args) { - c3_chart_fn.data.names.bind(this)(args.names); - } - // update classes if exists - if ('classes' in args) { - Object.keys(args.classes).forEach(function (id) { - config.data_classes[id] = args.classes[id]; - }); - } - // update categories if exists - if ('categories' in args && $$.isCategorized()) { - config.axis_x_categories = args.categories; - } - // update axes if exists - if ('axes' in args) { - Object.keys(args.axes).forEach(function (id) { - config.data_axes[id] = args.axes[id]; - }); - } - // update colors if exists - if ('colors' in args) { - Object.keys(args.colors).forEach(function (id) { - config.data_colors[id] = args.colors[id]; - }); - } - // use cache if exists - if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) { - $$.load($$.getCaches(args.cacheIds), args.done); - return; - } - // unload if needed - if ('unload' in args) { - // TODO: do not unload if target will load (included in url/rows/columns) - $$.unload($$.mapToTargetIds((typeof args.unload === 'boolean' && args.unload) ? null : args.unload), function () { - $$.loadFromArgs(args); - }); - } else { - $$.loadFromArgs(args); - } - }; - - c3_chart_fn.unload = function (args) { - var $$ = this.internal; - args = args || {}; - if (args instanceof Array) { - args = {ids: args}; - } else if (typeof args === 'string') { - args = {ids: [args]}; - } - $$.unload($$.mapToTargetIds(args.ids), function () { - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); - if (args.done) { args.done(); } - }); - }; - - c3_chart_fn.flow = function (args) { - var $$ = this.internal, - targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(), - dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to; - - if (args.json) { - data = $$.convertJsonToData(args.json, args.keys); - } - else if (args.rows) { - data = $$.convertRowsToData(args.rows); - } - else if (args.columns) { - data = $$.convertColumnsToData(args.columns); - } - else { - return; - } - targets = $$.convertDataToTargets(data, true); - - // Update/Add data - $$.data.targets.forEach(function (t) { - var found = false, i, j; - for (i = 0; i < targets.length; i++) { - if (t.id === targets[i].id) { - found = true; - - if (t.values[t.values.length - 1]) { - tail = t.values[t.values.length - 1].index + 1; - } - length = targets[i].values.length; - - for (j = 0; j < length; j++) { - targets[i].values[j].index = tail + j; - if (!$$.isTimeSeries()) { - targets[i].values[j].x = tail + j; - } - } - t.values = t.values.concat(targets[i].values); - - targets.splice(i, 1); - break; - } - } - if (!found) { notfoundIds.push(t.id); } - }); - - // Append null for not found targets - $$.data.targets.forEach(function (t) { - var i, j; - for (i = 0; i < notfoundIds.length; i++) { - if (t.id === notfoundIds[i]) { - tail = t.values[t.values.length - 1].index + 1; - for (j = 0; j < length; j++) { - t.values.push({ - id: t.id, - index: tail + j, - x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j, - value: null - }); - } - } - } - }); - - // Generate null values for new target - if ($$.data.targets.length) { - targets.forEach(function (t) { - var i, missing = []; - for (i = $$.data.targets[0].values[0].index; i < tail; i++) { - missing.push({ - id: t.id, - index: i, - x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i, - value: null - }); - } - t.values.forEach(function (v) { - v.index += tail; - if (!$$.isTimeSeries()) { - v.x += tail; - } - }); - t.values = missing.concat(t.values); - }); - } - $$.data.targets = $$.data.targets.concat(targets); // add remained - - // check data count because behavior needs to change when it's only one - dataCount = $$.getMaxDataCount(); - baseTarget = $$.data.targets[0]; - baseValue = baseTarget.values[0]; - - // Update length to flow if needed - if (isDefined(args.to)) { - length = 0; - to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to; - baseTarget.values.forEach(function (v) { - if (v.x < to) { length++; } - }); - } else if (isDefined(args.length)) { - length = args.length; - } - - // If only one data, update the domain to flow from left edge of the chart - if (!orgDataCount) { - if ($$.isTimeSeries()) { - if (baseTarget.values.length > 1) { - diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x; - } else { - diff = baseValue.x - $$.getXDomain($$.data.targets)[0]; - } - } else { - diff = 1; - } - domain = [baseValue.x - diff, baseValue.x]; - $$.updateXDomain(null, true, true, false, domain); - } else if (orgDataCount === 1) { - if ($$.isTimeSeries()) { - diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2; - domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)]; - $$.updateXDomain(null, true, true, false, domain); - } - } - - // Set targets - $$.updateTargets($$.data.targets); - - // Redraw with new targets - $$.redraw({ - flow: { - index: baseValue.index, - length: length, - duration: isValue(args.duration) ? args.duration : $$.config.transition_duration, - done: args.done, - orgDataCount: orgDataCount, - }, - withLegend: true, - withTransition: orgDataCount > 1, - withTrimXDomain: false, - withUpdateXAxis: true, - }); - }; - - c3_chart_internal_fn.generateFlow = function (args) { - var $$ = this, config = $$.config, d3 = $$.d3; - - return function () { - var targets = args.targets, - flow = args.flow, - drawBar = args.drawBar, - drawLine = args.drawLine, - drawArea = args.drawArea, - cx = args.cx, - cy = args.cy, - xv = args.xv, - xForText = args.xForText, - yForText = args.yForText, - duration = args.duration; - - var translateX, scaleX = 1, transform, - flowIndex = flow.index, - flowLength = flow.length, - flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex), - flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength), - orgDomain = $$.x.domain(), domain, - durationForFlow = flow.duration || duration, - done = flow.done || function () {}, - wait = $$.generateWait(); - - var xgrid = $$.xgrid || d3.selectAll([]), - xgridLines = $$.xgridLines || d3.selectAll([]), - mainRegion = $$.mainRegion || d3.selectAll([]), - mainText = $$.mainText || d3.selectAll([]), - mainBar = $$.mainBar || d3.selectAll([]), - mainLine = $$.mainLine || d3.selectAll([]), - mainArea = $$.mainArea || d3.selectAll([]), - mainCircle = $$.mainCircle || d3.selectAll([]); - - // set flag - $$.flowing = true; - - // remove head data after rendered - $$.data.targets.forEach(function (d) { - d.values.splice(0, flowLength); - }); - - // update x domain to generate axis elements for flow - domain = $$.updateXDomain(targets, true, true); - // update elements related to x scale - if ($$.updateXGrid) { $$.updateXGrid(true); } - - // generate transform to flow - if (!flow.orgDataCount) { // if empty - if ($$.data.targets[0].values.length !== 1) { - translateX = $$.x(orgDomain[0]) - $$.x(domain[0]); - } else { - if ($$.isTimeSeries()) { - flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0); - flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1); - translateX = $$.x(flowStart.x) - $$.x(flowEnd.x); - } else { - translateX = diffDomain(domain) / 2; - } - } - } else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) { - translateX = $$.x(orgDomain[0]) - $$.x(domain[0]); - } else { - if ($$.isTimeSeries()) { - translateX = ($$.x(orgDomain[0]) - $$.x(domain[0])); - } else { - translateX = ($$.x(flowStart.x) - $$.x(flowEnd.x)); - } - } - scaleX = (diffDomain(orgDomain) / diffDomain(domain)); - transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)'; - - $$.hideXGridFocus(); - - d3.transition().ease('linear').duration(durationForFlow).each(function () { - wait.add($$.axes.x.transition().call($$.xAxis)); - wait.add(mainBar.transition().attr('transform', transform)); - wait.add(mainLine.transition().attr('transform', transform)); - wait.add(mainArea.transition().attr('transform', transform)); - wait.add(mainCircle.transition().attr('transform', transform)); - wait.add(mainText.transition().attr('transform', transform)); - wait.add(mainRegion.filter($$.isRegionOnX).transition().attr('transform', transform)); - wait.add(xgrid.transition().attr('transform', transform)); - wait.add(xgridLines.transition().attr('transform', transform)); - }) - .call(wait, function () { - var i, shapes = [], texts = [], eventRects = []; - - // remove flowed elements - if (flowLength) { - for (i = 0; i < flowLength; i++) { - shapes.push('.' + CLASS.shape + '-' + (flowIndex + i)); - texts.push('.' + CLASS.text + '-' + (flowIndex + i)); - eventRects.push('.' + CLASS.eventRect + '-' + (flowIndex + i)); - } - $$.svg.selectAll('.' + CLASS.shapes).selectAll(shapes).remove(); - $$.svg.selectAll('.' + CLASS.texts).selectAll(texts).remove(); - $$.svg.selectAll('.' + CLASS.eventRects).selectAll(eventRects).remove(); - $$.svg.select('.' + CLASS.xgrid).remove(); - } - - // draw again for removing flowed elements and reverting attr - xgrid - .attr('transform', null) - .attr($$.xgridAttr); - xgridLines - .attr('transform', null); - xgridLines.select('line') - .attr("x1", config.axis_rotated ? 0 : xv) - .attr("x2", config.axis_rotated ? $$.width : xv); - xgridLines.select('text') - .attr("x", config.axis_rotated ? $$.width : 0) - .attr("y", xv); - mainBar - .attr('transform', null) - .attr("d", drawBar); - mainLine - .attr('transform', null) - .attr("d", drawLine); - mainArea - .attr('transform', null) - .attr("d", drawArea); - mainCircle - .attr('transform', null) - .attr("cx", cx) - .attr("cy", cy); - mainText - .attr('transform', null) - .attr('x', xForText) - .attr('y', yForText) - .style('fill-opacity', $$.opacityForText.bind($$)); - mainRegion - .attr('transform', null); - mainRegion.select('rect').filter($$.isRegionOnX) - .attr("x", $$.regionX.bind($$)) - .attr("width", $$.regionWidth.bind($$)); - - if (config.interaction_enabled) { - $$.redrawEventRect(); - } - - // callback for end of flow - done(); - - $$.flowing = false; - }); - }; - }; - - c3_chart_fn.selected = function (targetId) { - var $$ = this.internal, d3 = $$.d3; - return d3.merge( - $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape) - .filter(function () { return d3.select(this).classed(CLASS.SELECTED); }) - .map(function (d) { return d.map(function (d) { var data = d.__data__; return data.data ? data.data : data; }); }) - ); - }; - c3_chart_fn.select = function (ids, indices, resetOther) { - var $$ = this.internal, d3 = $$.d3, config = $$.config; - if (! config.data_selection_enabled) { return; } - $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { - var shape = d3.select(this), id = d.data ? d.data.id : d.id, - toggle = $$.getToggle(this, d).bind($$), - isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, - isTargetIndex = !indices || indices.indexOf(i) >= 0, - isSelected = shape.classed(CLASS.SELECTED); - // line/area selection not supported yet - if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { - return; - } - if (isTargetId && isTargetIndex) { - if (config.data_selection_isselectable(d) && !isSelected) { - toggle(true, shape.classed(CLASS.SELECTED, true), d, i); - } - } else if (isDefined(resetOther) && resetOther) { - if (isSelected) { - toggle(false, shape.classed(CLASS.SELECTED, false), d, i); - } - } - }); - }; - c3_chart_fn.unselect = function (ids, indices) { - var $$ = this.internal, d3 = $$.d3, config = $$.config; - if (! config.data_selection_enabled) { return; } - $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { - var shape = d3.select(this), id = d.data ? d.data.id : d.id, - toggle = $$.getToggle(this, d).bind($$), - isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, - isTargetIndex = !indices || indices.indexOf(i) >= 0, - isSelected = shape.classed(CLASS.SELECTED); - // line/area selection not supported yet - if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { - return; - } - if (isTargetId && isTargetIndex) { - if (config.data_selection_isselectable(d)) { - if (isSelected) { - toggle(false, shape.classed(CLASS.SELECTED, false), d, i); - } - } - } - }); - }; - - c3_chart_fn.transform = function (type, targetIds) { - var $$ = this.internal, - options = ['pie', 'donut'].indexOf(type) >= 0 ? {withTransform: true} : null; - $$.transformTo(targetIds, type, options); - }; - - c3_chart_internal_fn.transformTo = function (targetIds, type, optionsForRedraw) { - var $$ = this, - withTransitionForAxis = !$$.hasArcType(), - options = optionsForRedraw || {withTransitionForAxis: withTransitionForAxis}; - options.withTransitionForTransform = false; - $$.transiting = false; - $$.setTargetType(targetIds, type); - $$.updateTargets($$.data.targets); // this is needed when transforming to arc - $$.updateAndRedraw(options); - }; - - c3_chart_fn.groups = function (groups) { - var $$ = this.internal, config = $$.config; - if (isUndefined(groups)) { return config.data_groups; } - config.data_groups = groups; - $$.redraw(); - return config.data_groups; - }; - - c3_chart_fn.xgrids = function (grids) { - var $$ = this.internal, config = $$.config; - if (! grids) { return config.grid_x_lines; } - config.grid_x_lines = grids; - $$.redrawWithoutRescale(); - return config.grid_x_lines; - }; - c3_chart_fn.xgrids.add = function (grids) { - var $$ = this.internal; - return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : [])); - }; - c3_chart_fn.xgrids.remove = function (params) { // TODO: multiple - var $$ = this.internal; - $$.removeGridLines(params, true); - }; - - c3_chart_fn.ygrids = function (grids) { - var $$ = this.internal, config = $$.config; - if (! grids) { return config.grid_y_lines; } - config.grid_y_lines = grids; - $$.redrawWithoutRescale(); - return config.grid_y_lines; - }; - c3_chart_fn.ygrids.add = function (grids) { - var $$ = this.internal; - return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : [])); - }; - c3_chart_fn.ygrids.remove = function (params) { // TODO: multiple - var $$ = this.internal; - $$.removeGridLines(params, false); - }; - - c3_chart_fn.regions = function (regions) { - var $$ = this.internal, config = $$.config; - if (!regions) { return config.regions; } - config.regions = regions; - $$.redrawWithoutRescale(); - return config.regions; - }; - c3_chart_fn.regions.add = function (regions) { - var $$ = this.internal, config = $$.config; - if (!regions) { return config.regions; } - config.regions = config.regions.concat(regions); - $$.redrawWithoutRescale(); - return config.regions; - }; - c3_chart_fn.regions.remove = function (options) { - var $$ = this.internal, config = $$.config, - duration, classes, regions; - - options = options || {}; - duration = $$.getOption(options, "duration", config.transition_duration); - classes = $$.getOption(options, "classes", [CLASS.region]); - - regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) { return '.' + c; })); - (duration ? regions.transition().duration(duration) : regions) - .style('opacity', 0) - .remove(); - - config.regions = config.regions.filter(function (region) { - var found = false; - if (!region['class']) { - return true; - } - region['class'].split(' ').forEach(function (c) { - if (classes.indexOf(c) >= 0) { found = true; } - }); - return !found; - }); - - return config.regions; - }; - - c3_chart_fn.data = function (targetIds) { - var targets = this.internal.data.targets; - return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) { - return [].concat(targetIds).indexOf(t.id) >= 0; - }); - }; - c3_chart_fn.data.shown = function (targetIds) { - return this.internal.filterTargetsToShow(this.data(targetIds)); - }; - c3_chart_fn.data.values = function (targetId) { - var targets, values = null; - if (targetId) { - targets = this.data(targetId); - values = targets[0] ? targets[0].values.map(function (d) { return d.value; }) : null; - } - return values; - }; - c3_chart_fn.data.names = function (names) { - this.internal.clearLegendItemTextBoxCache(); - return this.internal.updateDataAttributes('names', names); - }; - c3_chart_fn.data.colors = function (colors) { - return this.internal.updateDataAttributes('colors', colors); - }; - c3_chart_fn.data.axes = function (axes) { - return this.internal.updateDataAttributes('axes', axes); - }; - - c3_chart_fn.category = function (i, category) { - var $$ = this.internal, config = $$.config; - if (arguments.length > 1) { - config.axis_x_categories[i] = category; - $$.redraw(); - } - return config.axis_x_categories[i]; - }; - c3_chart_fn.categories = function (categories) { - var $$ = this.internal, config = $$.config; - if (!arguments.length) { return config.axis_x_categories; } - config.axis_x_categories = categories; - $$.redraw(); - return config.axis_x_categories; - }; - - // TODO: fix - c3_chart_fn.color = function (id) { - var $$ = this.internal; - return $$.color(id); // more patterns - }; - - c3_chart_fn.x = function (x) { - var $$ = this.internal; - if (arguments.length) { - $$.updateTargetX($$.data.targets, x); - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); - } - return $$.data.xs; - }; - c3_chart_fn.xs = function (xs) { - var $$ = this.internal; - if (arguments.length) { - $$.updateTargetXs($$.data.targets, xs); - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); - } - return $$.data.xs; - }; - - c3_chart_fn.axis = function () {}; - c3_chart_fn.axis.labels = function (labels) { - var $$ = this.internal; - if (arguments.length) { - Object.keys(labels).forEach(function (axisId) { - $$.axis.setLabelText(axisId, labels[axisId]); - }); - $$.axis.updateLabels(); - } - // TODO: return some values? - }; - c3_chart_fn.axis.max = function (max) { - var $$ = this.internal, config = $$.config; - if (arguments.length) { - if (typeof max === 'object') { - if (isValue(max.x)) { config.axis_x_max = max.x; } - if (isValue(max.y)) { config.axis_y_max = max.y; } - if (isValue(max.y2)) { config.axis_y2_max = max.y2; } - } else { - config.axis_y_max = config.axis_y2_max = max; - } - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); - } else { - return { - x: config.axis_x_max, - y: config.axis_y_max, - y2: config.axis_y2_max - }; - } - }; - c3_chart_fn.axis.min = function (min) { - var $$ = this.internal, config = $$.config; - if (arguments.length) { - if (typeof min === 'object') { - if (isValue(min.x)) { config.axis_x_min = min.x; } - if (isValue(min.y)) { config.axis_y_min = min.y; } - if (isValue(min.y2)) { config.axis_y2_min = min.y2; } - } else { - config.axis_y_min = config.axis_y2_min = min; - } - $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); - } else { - return { - x: config.axis_x_min, - y: config.axis_y_min, - y2: config.axis_y2_min - }; - } - }; - c3_chart_fn.axis.range = function (range) { - if (arguments.length) { - if (isDefined(range.max)) { this.axis.max(range.max); } - if (isDefined(range.min)) { this.axis.min(range.min); } - } else { - return { - max: this.axis.max(), - min: this.axis.min() - }; - } - }; - - c3_chart_fn.legend = function () {}; - c3_chart_fn.legend.show = function (targetIds) { - var $$ = this.internal; - $$.showLegend($$.mapToTargetIds(targetIds)); - $$.updateAndRedraw({withLegend: true}); - }; - c3_chart_fn.legend.hide = function (targetIds) { - var $$ = this.internal; - $$.hideLegend($$.mapToTargetIds(targetIds)); - $$.updateAndRedraw({withLegend: true}); - }; - - c3_chart_fn.resize = function (size) { - var $$ = this.internal, config = $$.config; - config.size_width = size ? size.width : null; - config.size_height = size ? size.height : null; - this.flush(); - }; - - c3_chart_fn.flush = function () { - var $$ = this.internal; - $$.updateAndRedraw({withLegend: true, withTransition: false, withTransitionForTransform: false}); - }; - - c3_chart_fn.destroy = function () { - var $$ = this.internal; - - window.clearInterval($$.intervalForObserveInserted); - - if ($$.resizeTimeout !== undefined) { - window.clearTimeout($$.resizeTimeout); - } - - if (window.detachEvent) { - window.detachEvent('onresize', $$.resizeFunction); - } else if (window.removeEventListener) { - window.removeEventListener('resize', $$.resizeFunction); - } else { - var wrapper = window.onresize; - // check if no one else removed our wrapper and remove our resizeFunction from it - if (wrapper && wrapper.add && wrapper.remove) { - wrapper.remove($$.resizeFunction); - } - } - - $$.selectChart.classed('c3', false).html(""); - - // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen. - Object.keys($$).forEach(function (key) { - $$[key] = null; - }); - - return null; - }; - - c3_chart_fn.tooltip = function () {}; - c3_chart_fn.tooltip.show = function (args) { - var $$ = this.internal, index, mouse; - - // determine mouse position on the chart - if (args.mouse) { - mouse = args.mouse; - } - - // determine focus data - if (args.data) { - if ($$.isMultipleX()) { - // if multiple xs, target point will be determined by mouse - mouse = [$$.x(args.data.x), $$.getYScale(args.data.id)(args.data.value)]; - index = null; - } else { - // TODO: when tooltip_grouped = false - index = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x); - } - } - else if (typeof args.x !== 'undefined') { - index = $$.getIndexByX(args.x); - } - else if (typeof args.index !== 'undefined') { - index = args.index; - } - - // emulate mouse events to show - $$.dispatchEvent('mouseover', index, mouse); - $$.dispatchEvent('mousemove', index, mouse); - - $$.config.tooltip_onshow.call($$, args.data); - }; - c3_chart_fn.tooltip.hide = function () { - // TODO: get target data by checking the state of focus - this.internal.dispatchEvent('mouseout', 0); - - this.internal.config.tooltip_onhide.call(this); - }; - - // Features: - // 1. category axis - // 2. ceil values of translate/x/y to int for half pixel antialiasing - // 3. multiline tick text - var tickTextCharSize; - function c3_axis(d3, params) { - var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize, tickPadding = 3, tickValues = null, tickFormat, tickArguments; - - var tickOffset = 0, tickCulling = true, tickCentered; - - params = params || {}; - outerTickSize = params.withOuterTick ? 6 : 0; - - function axisX(selection, x) { - selection.attr("transform", function (d) { - return "translate(" + Math.ceil(x(d) + tickOffset) + ", 0)"; - }); - } - function axisY(selection, y) { - selection.attr("transform", function (d) { - return "translate(0," + Math.ceil(y(d)) + ")"; - }); - } - function scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; - } - function generateTicks(scale) { - var i, domain, ticks = []; - if (scale.ticks) { - return scale.ticks.apply(scale, tickArguments); - } - domain = scale.domain(); - for (i = Math.ceil(domain[0]); i < domain[1]; i++) { - ticks.push(i); - } - if (ticks.length > 0 && ticks[0] > 0) { - ticks.unshift(ticks[0] - (ticks[1] - ticks[0])); - } - return ticks; - } - function copyScale() { - var newScale = scale.copy(), domain; - if (params.isCategory) { - domain = scale.domain(); - newScale.domain([domain[0], domain[1] - 1]); - } - return newScale; - } - function textFormatted(v) { - var formatted = tickFormat ? tickFormat(v) : v; - return typeof formatted !== 'undefined' ? formatted : ''; - } - function getSizeFor1Char(tick) { - if (tickTextCharSize) { - return tickTextCharSize; - } - var size = { - h: 11.5, - w: 5.5 - }; - tick.select('text').text(textFormatted).each(function (d) { - var box = this.getBoundingClientRect(), - text = textFormatted(d), - h = box.height, - w = text ? (box.width / text.length) : undefined; - if (h && w) { - size.h = h; - size.w = w; - } - }).text(''); - tickTextCharSize = size; - return size; - } - function transitionise(selection) { - return params.withoutTransition ? selection : d3.transition(selection); - } - function axis(g) { - g.each(function () { - var g = axis.g = d3.select(this); - - var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = copyScale(); - - var ticks = tickValues ? tickValues : generateTicks(scale1), - tick = g.selectAll(".tick").data(ticks, scale1), - tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", 1e-6), - // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks. - tickExit = tick.exit().remove(), - tickUpdate = transitionise(tick).style("opacity", 1), - tickTransform, tickX, tickY; - - var range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()), - path = g.selectAll(".domain").data([ 0 ]), - pathUpdate = (path.enter().append("path").attr("class", "domain"), transitionise(path)); - tickEnter.append("line"); - tickEnter.append("text"); - - var lineEnter = tickEnter.select("line"), - lineUpdate = tickUpdate.select("line"), - textEnter = tickEnter.select("text"), - textUpdate = tickUpdate.select("text"); - - if (params.isCategory) { - tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2); - tickX = tickCentered ? 0 : tickOffset; - tickY = tickCentered ? tickOffset : 0; - } else { - tickOffset = tickX = 0; - } - - var text, tspan, sizeFor1Char = getSizeFor1Char(g.select('.tick')), counts = []; - var tickLength = Math.max(innerTickSize, 0) + tickPadding, - isVertical = orient === 'left' || orient === 'right'; - - // this should be called only when category axis - function splitTickText(d, maxWidth) { - var tickText = textFormatted(d), - subtext, spaceIndex, textWidth, splitted = []; - - if (Object.prototype.toString.call(tickText) === "[object Array]") { - return tickText; - } - - if (!maxWidth || maxWidth <= 0) { - maxWidth = isVertical ? 95 : params.isCategory ? (Math.ceil(scale1(ticks[1]) - scale1(ticks[0])) - 12) : 110; - } - - function split(splitted, text) { - spaceIndex = undefined; - for (var i = 1; i < text.length; i++) { - if (text.charAt(i) === ' ') { - spaceIndex = i; - } - subtext = text.substr(0, i + 1); - textWidth = sizeFor1Char.w * subtext.length; - // if text width gets over tick width, split by space index or crrent index - if (maxWidth < textWidth) { - return split( - splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)), - text.slice(spaceIndex ? spaceIndex + 1 : i) - ); - } - } - return splitted.concat(text); - } - - return split(splitted, tickText + ""); - } - - function tspanDy(d, i) { - var dy = sizeFor1Char.h; - if (i === 0) { - if (orient === 'left' || orient === 'right') { - dy = -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3); - } else { - dy = ".71em"; - } - } - return dy; - } - - function tickSize(d) { - var tickPosition = scale(d) + (tickCentered ? 0 : tickOffset); - return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0; - } - - text = tick.select("text"); - tspan = text.selectAll('tspan') - .data(function (d, i) { - var splitted = params.tickMultiline ? splitTickText(d, params.tickWidth) : [].concat(textFormatted(d)); - counts[i] = splitted.length; - return splitted.map(function (s) { - return { index: i, splitted: s }; - }); - }); - tspan.enter().append('tspan'); - tspan.exit().remove(); - tspan.text(function (d) { return d.splitted; }); - - var rotate = params.tickTextRotate; - - function textAnchorForText(rotate) { - if (!rotate) { - return 'middle'; - } - return rotate > 0 ? "start" : "end"; - } - function textTransform(rotate) { - if (!rotate) { - return ''; - } - return "rotate(" + rotate + ")"; - } - function dxForText(rotate) { - if (!rotate) { - return 0; - } - return 8 * Math.sin(Math.PI * (rotate / 180)); - } - function yForText(rotate) { - if (!rotate) { - return tickLength; - } - return 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1); - } - - switch (orient) { - case "bottom": - { - tickTransform = axisX; - lineEnter.attr("y2", innerTickSize); - textEnter.attr("y", tickLength); - lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", tickSize); - textUpdate.attr("x", 0).attr("y", yForText(rotate)) - .style("text-anchor", textAnchorForText(rotate)) - .attr("transform", textTransform(rotate)); - tspan.attr('x', 0).attr("dy", tspanDy).attr('dx', dxForText(rotate)); - pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize); - break; - } - case "top": - { - // TODO: rotated tick text - tickTransform = axisX; - lineEnter.attr("y2", -innerTickSize); - textEnter.attr("y", -tickLength); - lineUpdate.attr("x2", 0).attr("y2", -innerTickSize); - textUpdate.attr("x", 0).attr("y", -tickLength); - text.style("text-anchor", "middle"); - tspan.attr('x', 0).attr("dy", "0em"); - pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize); - break; - } - case "left": - { - tickTransform = axisY; - lineEnter.attr("x2", -innerTickSize); - textEnter.attr("x", -tickLength); - lineUpdate.attr("x2", -innerTickSize).attr("y1", tickY).attr("y2", tickY); - textUpdate.attr("x", -tickLength).attr("y", tickOffset); - text.style("text-anchor", "end"); - tspan.attr('x', -tickLength).attr("dy", tspanDy); - pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize); - break; - } - case "right": - { - tickTransform = axisY; - lineEnter.attr("x2", innerTickSize); - textEnter.attr("x", tickLength); - lineUpdate.attr("x2", innerTickSize).attr("y2", 0); - textUpdate.attr("x", tickLength).attr("y", 0); - text.style("text-anchor", "start"); - tspan.attr('x', tickLength).attr("dy", tspanDy); - pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize); - break; - } - } - if (scale1.rangeBand) { - var x = scale1, dx = x.rangeBand() / 2; - scale0 = scale1 = function (d) { - return x(d) + dx; - }; - } else if (scale0.rangeBand) { - scale0 = scale1; - } else { - tickExit.call(tickTransform, scale1); - } - tickEnter.call(tickTransform, scale0); - tickUpdate.call(tickTransform, scale1); - }); - } - axis.scale = function (x) { - if (!arguments.length) { return scale; } - scale = x; - return axis; - }; - axis.orient = function (x) { - if (!arguments.length) { return orient; } - orient = x in {top: 1, right: 1, bottom: 1, left: 1} ? x + "" : "bottom"; - return axis; - }; - axis.tickFormat = function (format) { - if (!arguments.length) { return tickFormat; } - tickFormat = format; - return axis; - }; - axis.tickCentered = function (isCentered) { - if (!arguments.length) { return tickCentered; } - tickCentered = isCentered; - return axis; - }; - axis.tickOffset = function () { - return tickOffset; - }; - axis.tickInterval = function () { - var interval, length; - if (params.isCategory) { - interval = tickOffset * 2; - } - else { - length = axis.g.select('path.domain').node().getTotalLength() - outerTickSize * 2; - interval = length / axis.g.selectAll('line').size(); - } - return interval === Infinity ? 0 : interval; - }; - axis.ticks = function () { - if (!arguments.length) { return tickArguments; } - tickArguments = arguments; - return axis; - }; - axis.tickCulling = function (culling) { - if (!arguments.length) { return tickCulling; } - tickCulling = culling; - return axis; - }; - axis.tickValues = function (x) { - if (typeof x === 'function') { - tickValues = function () { - return x(scale.domain()); - }; - } - else { - if (!arguments.length) { return tickValues; } - tickValues = x; - } - return axis; - }; - return axis; - } - - c3_chart_internal_fn.isSafari = function () { - var ua = window.navigator.userAgent; - return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0; - }; - c3_chart_internal_fn.isChrome = function () { - var ua = window.navigator.userAgent; - return ua.indexOf('Chrome') >= 0; - }; - - /* jshint ignore:start */ - - // PhantomJS doesn't have support for Function.prototype.bind, which has caused confusion. Use - // this polyfill to avoid the confusion. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill - - if (!Function.prototype.bind) { - Function.prototype.bind = function(oThis) { - if (typeof this !== 'function') { - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function() {}, - fBound = function() { - return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); - }; - - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - - return fBound; - }; - } - - //SVGPathSeg API polyfill - //https://github.com/progers/pathseg - // - //This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from - //SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec - //changes which were implemented in Firefox 43 and Chrome 46. - //Chrome 48 removes these APIs, so this polyfill is required. - - (function() { "use strict"; - if (!("SVGPathSeg" in window)) { - // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg - window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) { - this.pathSegType = type; - this.pathSegTypeAsLetter = typeAsLetter; - this._owningPathSegList = owningPathSegList; - } - - SVGPathSeg.PATHSEG_UNKNOWN = 0; - SVGPathSeg.PATHSEG_CLOSEPATH = 1; - SVGPathSeg.PATHSEG_MOVETO_ABS = 2; - SVGPathSeg.PATHSEG_MOVETO_REL = 3; - SVGPathSeg.PATHSEG_LINETO_ABS = 4; - SVGPathSeg.PATHSEG_LINETO_REL = 5; - SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6; - SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7; - SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8; - SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9; - SVGPathSeg.PATHSEG_ARC_ABS = 10; - SVGPathSeg.PATHSEG_ARC_REL = 11; - SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12; - SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13; - SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14; - SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15; - SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16; - SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17; - SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18; - SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19; - - // Notify owning PathSegList on any changes so they can be synchronized back to the path element. - SVGPathSeg.prototype._segmentChanged = function() { - if (this._owningPathSegList) - this._owningPathSegList.segmentChanged(this); - } - - window.SVGPathSegClosePath = function(owningPathSegList) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList); - } - SVGPathSegClosePath.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegClosePath.prototype.toString = function() { return "[object SVGPathSegClosePath]"; } - SVGPathSegClosePath.prototype._asPathString = function() { return this.pathSegTypeAsLetter; } - SVGPathSegClosePath.prototype.clone = function() { return new SVGPathSegClosePath(undefined); } - - window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList); - this._x = x; - this._y = y; - } - SVGPathSegMovetoAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegMovetoAbs.prototype.toString = function() { return "[object SVGPathSegMovetoAbs]"; } - SVGPathSegMovetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; } - SVGPathSegMovetoAbs.prototype.clone = function() { return new SVGPathSegMovetoAbs(undefined, this._x, this._y); } - Object.defineProperty(SVGPathSegMovetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegMovetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList); - this._x = x; - this._y = y; - } - SVGPathSegMovetoRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegMovetoRel.prototype.toString = function() { return "[object SVGPathSegMovetoRel]"; } - SVGPathSegMovetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; } - SVGPathSegMovetoRel.prototype.clone = function() { return new SVGPathSegMovetoRel(undefined, this._x, this._y); } - Object.defineProperty(SVGPathSegMovetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegMovetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList); - this._x = x; - this._y = y; - } - SVGPathSegLinetoAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegLinetoAbs.prototype.toString = function() { return "[object SVGPathSegLinetoAbs]"; } - SVGPathSegLinetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; } - SVGPathSegLinetoAbs.prototype.clone = function() { return new SVGPathSegLinetoAbs(undefined, this._x, this._y); } - Object.defineProperty(SVGPathSegLinetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegLinetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList); - this._x = x; - this._y = y; - } - SVGPathSegLinetoRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegLinetoRel.prototype.toString = function() { return "[object SVGPathSegLinetoRel]"; } - SVGPathSegLinetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; } - SVGPathSegLinetoRel.prototype.clone = function() { return new SVGPathSegLinetoRel(undefined, this._x, this._y); } - Object.defineProperty(SVGPathSegLinetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegLinetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoCubicAbs = function(owningPathSegList, x, y, x1, y1, x2, y2) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList); - this._x = x; - this._y = y; - this._x1 = x1; - this._y1 = y1; - this._x2 = x2; - this._y2 = y2; - } - SVGPathSegCurvetoCubicAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoCubicAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicAbs]"; } - SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; } - SVGPathSegCurvetoCubicAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); } - Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoCubicRel = function(owningPathSegList, x, y, x1, y1, x2, y2) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList); - this._x = x; - this._y = y; - this._x1 = x1; - this._y1 = y1; - this._x2 = x2; - this._y2 = y2; - } - SVGPathSegCurvetoCubicRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoCubicRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicRel]"; } - SVGPathSegCurvetoCubicRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; } - SVGPathSegCurvetoCubicRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); } - Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoQuadraticAbs = function(owningPathSegList, x, y, x1, y1) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList); - this._x = x; - this._y = y; - this._x1 = x1; - this._y1 = y1; - } - SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticAbs]"; } - SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; } - SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); } - Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoQuadraticRel = function(owningPathSegList, x, y, x1, y1) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList); - this._x = x; - this._y = y; - this._x1 = x1; - this._y1 = y1; - } - SVGPathSegCurvetoQuadraticRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoQuadraticRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticRel]"; } - SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; } - SVGPathSegCurvetoQuadraticRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); } - Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegArcAbs = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList); - this._x = x; - this._y = y; - this._r1 = r1; - this._r2 = r2; - this._angle = angle; - this._largeArcFlag = largeArcFlag; - this._sweepFlag = sweepFlag; - } - SVGPathSegArcAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegArcAbs.prototype.toString = function() { return "[object SVGPathSegArcAbs]"; } - SVGPathSegArcAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; } - SVGPathSegArcAbs.prototype.clone = function() { return new SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); } - Object.defineProperty(SVGPathSegArcAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcAbs.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcAbs.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcAbs.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcAbs.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcAbs.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegArcRel = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList); - this._x = x; - this._y = y; - this._r1 = r1; - this._r2 = r2; - this._angle = angle; - this._largeArcFlag = largeArcFlag; - this._sweepFlag = sweepFlag; - } - SVGPathSegArcRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegArcRel.prototype.toString = function() { return "[object SVGPathSegArcRel]"; } - SVGPathSegArcRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; } - SVGPathSegArcRel.prototype.clone = function() { return new SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); } - Object.defineProperty(SVGPathSegArcRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcRel.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcRel.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcRel.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcRel.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegArcRel.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList); - this._x = x; - } - SVGPathSegLinetoHorizontalAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegLinetoHorizontalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalAbs]"; } - SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; } - SVGPathSegLinetoHorizontalAbs.prototype.clone = function() { return new SVGPathSegLinetoHorizontalAbs(undefined, this._x); } - Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList); - this._x = x; - } - SVGPathSegLinetoHorizontalRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegLinetoHorizontalRel.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalRel]"; } - SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; } - SVGPathSegLinetoHorizontalRel.prototype.clone = function() { return new SVGPathSegLinetoHorizontalRel(undefined, this._x); } - Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList); - this._y = y; - } - SVGPathSegLinetoVerticalAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegLinetoVerticalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalAbs]"; } - SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; } - SVGPathSegLinetoVerticalAbs.prototype.clone = function() { return new SVGPathSegLinetoVerticalAbs(undefined, this._y); } - Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList); - this._y = y; - } - SVGPathSegLinetoVerticalRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegLinetoVerticalRel.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalRel]"; } - SVGPathSegLinetoVerticalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; } - SVGPathSegLinetoVerticalRel.prototype.clone = function() { return new SVGPathSegLinetoVerticalRel(undefined, this._y); } - Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoCubicSmoothAbs = function(owningPathSegList, x, y, x2, y2) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList); - this._x = x; - this._y = y; - this._x2 = x2; - this._y2 = y2; - } - SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothAbs]"; } - SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; } - SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); } - Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoCubicSmoothRel = function(owningPathSegList, x, y, x2, y2) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList); - this._x = x; - this._y = y; - this._x2 = x2; - this._y2 = y2; - } - SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothRel]"; } - SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; } - SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); } - Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoQuadraticSmoothAbs = function(owningPathSegList, x, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList); - this._x = x; - this._y = y; - } - SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothAbs]"; } - SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; } - SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); } - Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - window.SVGPathSegCurvetoQuadraticSmoothRel = function(owningPathSegList, x, y) { - SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList); - this._x = x; - this._y = y; - } - SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(SVGPathSeg.prototype); - SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothRel]"; } - SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; } - SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); } - Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true }); - Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true }); - - // Add createSVGPathSeg* functions to SVGPathElement. - // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement. - SVGPathElement.prototype.createSVGPathSegClosePath = function() { return new SVGPathSegClosePath(undefined); } - SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) { return new SVGPathSegMovetoAbs(undefined, x, y); } - SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) { return new SVGPathSegMovetoRel(undefined, x, y); } - SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) { return new SVGPathSegLinetoAbs(undefined, x, y); } - SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) { return new SVGPathSegLinetoRel(undefined, x, y); } - SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); } - SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); } - SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); } - SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); } - SVGPathElement.prototype.createSVGPathSegArcAbs = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); } - SVGPathElement.prototype.createSVGPathSegArcRel = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); } - SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(x) { return new SVGPathSegLinetoHorizontalAbs(undefined, x); } - SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(x) { return new SVGPathSegLinetoHorizontalRel(undefined, x); } - SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(y) { return new SVGPathSegLinetoVerticalAbs(undefined, y); } - SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(y) { return new SVGPathSegLinetoVerticalRel(undefined, y); } - SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); } - SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); } - SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); } - SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); } - } - - if (!("SVGPathSegList" in window)) { - // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList - window.SVGPathSegList = function(pathElement) { - this._pathElement = pathElement; - this._list = this._parsePath(this._pathElement.getAttribute("d")); - - // Use a MutationObserver to catch changes to the path's "d" attribute. - this._mutationObserverConfig = { "attributes": true, "attributeFilter": ["d"] }; - this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this)); - this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); - } - - Object.defineProperty(SVGPathSegList.prototype, "numberOfItems", { - get: function() { - this._checkPathSynchronizedToList(); - return this._list.length; - }, - enumerable: true - }); - - // Add the pathSegList accessors to SVGPathElement. - // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData - Object.defineProperty(SVGPathElement.prototype, "pathSegList", { - get: function() { - if (!this._pathSegList) - this._pathSegList = new SVGPathSegList(this); - return this._pathSegList; - }, - enumerable: true - }); - // FIXME: The following are not implemented and simply return SVGPathElement.pathSegList. - Object.defineProperty(SVGPathElement.prototype, "normalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true }); - Object.defineProperty(SVGPathElement.prototype, "animatedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true }); - Object.defineProperty(SVGPathElement.prototype, "animatedNormalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true }); - - // Process any pending mutations to the path element and update the list as needed. - // This should be the first call of all public functions and is needed because - // MutationObservers are not synchronous so we can have pending asynchronous mutations. - SVGPathSegList.prototype._checkPathSynchronizedToList = function() { - this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords()); - } - - SVGPathSegList.prototype._updateListFromPathMutations = function(mutationRecords) { - if (!this._pathElement) - return; - var hasPathMutations = false; - mutationRecords.forEach(function(record) { - if (record.attributeName == "d") - hasPathMutations = true; - }); - if (hasPathMutations) - this._list = this._parsePath(this._pathElement.getAttribute("d")); - } - - // Serialize the list and update the path's 'd' attribute. - SVGPathSegList.prototype._writeListToPath = function() { - this._pathElementMutationObserver.disconnect(); - this._pathElement.setAttribute("d", SVGPathSegList._pathSegArrayAsString(this._list)); - this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig); - } - - // When a path segment changes the list needs to be synchronized back to the path element. - SVGPathSegList.prototype.segmentChanged = function(pathSeg) { - this._writeListToPath(); - } - - SVGPathSegList.prototype.clear = function() { - this._checkPathSynchronizedToList(); - - this._list.forEach(function(pathSeg) { - pathSeg._owningPathSegList = null; - }); - this._list = []; - this._writeListToPath(); - } - - SVGPathSegList.prototype.initialize = function(newItem) { - this._checkPathSynchronizedToList(); - - this._list = [newItem]; - newItem._owningPathSegList = this; - this._writeListToPath(); - return newItem; - } - - SVGPathSegList.prototype._checkValidIndex = function(index) { - if (isNaN(index) || index < 0 || index >= this.numberOfItems) - throw "INDEX_SIZE_ERR"; - } - - SVGPathSegList.prototype.getItem = function(index) { - this._checkPathSynchronizedToList(); - - this._checkValidIndex(index); - return this._list[index]; - } - - SVGPathSegList.prototype.insertItemBefore = function(newItem, index) { - this._checkPathSynchronizedToList(); - - // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list. - if (index > this.numberOfItems) - index = this.numberOfItems; - if (newItem._owningPathSegList) { - // SVG2 spec says to make a copy. - newItem = newItem.clone(); - } - this._list.splice(index, 0, newItem); - newItem._owningPathSegList = this; - this._writeListToPath(); - return newItem; - } - - SVGPathSegList.prototype.replaceItem = function(newItem, index) { - this._checkPathSynchronizedToList(); - - if (newItem._owningPathSegList) { - // SVG2 spec says to make a copy. - newItem = newItem.clone(); - } - this._checkValidIndex(index); - this._list[index] = newItem; - newItem._owningPathSegList = this; - this._writeListToPath(); - return newItem; - } - - SVGPathSegList.prototype.removeItem = function(index) { - this._checkPathSynchronizedToList(); - - this._checkValidIndex(index); - var item = this._list[index]; - this._list.splice(index, 1); - this._writeListToPath(); - return item; - } - - SVGPathSegList.prototype.appendItem = function(newItem) { - this._checkPathSynchronizedToList(); - - if (newItem._owningPathSegList) { - // SVG2 spec says to make a copy. - newItem = newItem.clone(); - } - this._list.push(newItem); - newItem._owningPathSegList = this; - // TODO: Optimize this to just append to the existing attribute. - this._writeListToPath(); - return newItem; - } - - SVGPathSegList._pathSegArrayAsString = function(pathSegArray) { - var string = ""; - var first = true; - pathSegArray.forEach(function(pathSeg) { - if (first) { - first = false; - string += pathSeg._asPathString(); - } else { - string += " " + pathSeg._asPathString(); - } - }); - return string; - } - - // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp. - SVGPathSegList.prototype._parsePath = function(string) { - if (!string || string.length == 0) - return []; - - var owningPathSegList = this; - - var Builder = function() { - this.pathSegList = []; - } - - Builder.prototype.appendSegment = function(pathSeg) { - this.pathSegList.push(pathSeg); - } - - var Source = function(string) { - this._string = string; - this._currentIndex = 0; - this._endIndex = this._string.length; - this._previousCommand = SVGPathSeg.PATHSEG_UNKNOWN; - - this._skipOptionalSpaces(); - } - - Source.prototype._isCurrentSpace = function() { - var character = this._string[this._currentIndex]; - return character <= " " && (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f"); - } - - Source.prototype._skipOptionalSpaces = function() { - while (this._currentIndex < this._endIndex && this._isCurrentSpace()) - this._currentIndex++; - return this._currentIndex < this._endIndex; - } - - Source.prototype._skipOptionalSpacesOrDelimiter = function() { - if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ",") - return false; - if (this._skipOptionalSpaces()) { - if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") { - this._currentIndex++; - this._skipOptionalSpaces(); - } - } - return this._currentIndex < this._endIndex; - } - - Source.prototype.hasMoreData = function() { - return this._currentIndex < this._endIndex; - } - - Source.prototype.peekSegmentType = function() { - var lookahead = this._string[this._currentIndex]; - return this._pathSegTypeFromChar(lookahead); - } - - Source.prototype._pathSegTypeFromChar = function(lookahead) { - switch (lookahead) { - case "Z": - case "z": - return SVGPathSeg.PATHSEG_CLOSEPATH; - case "M": - return SVGPathSeg.PATHSEG_MOVETO_ABS; - case "m": - return SVGPathSeg.PATHSEG_MOVETO_REL; - case "L": - return SVGPathSeg.PATHSEG_LINETO_ABS; - case "l": - return SVGPathSeg.PATHSEG_LINETO_REL; - case "C": - return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS; - case "c": - return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL; - case "Q": - return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS; - case "q": - return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL; - case "A": - return SVGPathSeg.PATHSEG_ARC_ABS; - case "a": - return SVGPathSeg.PATHSEG_ARC_REL; - case "H": - return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS; - case "h": - return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL; - case "V": - return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS; - case "v": - return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL; - case "S": - return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS; - case "s": - return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL; - case "T": - return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS; - case "t": - return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL; - default: - return SVGPathSeg.PATHSEG_UNKNOWN; - } - } - - Source.prototype._nextCommandHelper = function(lookahead, previousCommand) { - // Check for remaining coordinates in the current command. - if ((lookahead == "+" || lookahead == "-" || lookahead == "." || (lookahead >= "0" && lookahead <= "9")) && previousCommand != SVGPathSeg.PATHSEG_CLOSEPATH) { - if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_ABS) - return SVGPathSeg.PATHSEG_LINETO_ABS; - if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_REL) - return SVGPathSeg.PATHSEG_LINETO_REL; - return previousCommand; - } - return SVGPathSeg.PATHSEG_UNKNOWN; - } - - Source.prototype.initialCommandIsMoveTo = function() { - // If the path is empty it is still valid, so return true. - if (!this.hasMoreData()) - return true; - var command = this.peekSegmentType(); - // Path must start with moveTo. - return command == SVGPathSeg.PATHSEG_MOVETO_ABS || command == SVGPathSeg.PATHSEG_MOVETO_REL; - } - - // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp. - // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF - Source.prototype._parseNumber = function() { - var exponent = 0; - var integer = 0; - var frac = 1; - var decimal = 0; - var sign = 1; - var expsign = 1; - - var startIndex = this._currentIndex; - - this._skipOptionalSpaces(); - - // Read the sign. - if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+") - this._currentIndex++; - else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") { - this._currentIndex++; - sign = -1; - } - - if (this._currentIndex == this._endIndex || ((this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") && this._string.charAt(this._currentIndex) != ".")) - // The first character of a number must be one of [0-9+-.]. - return undefined; - - // Read the integer part, build right-to-left. - var startIntPartIndex = this._currentIndex; - while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") - this._currentIndex++; // Advance to first non-digit. - - if (this._currentIndex != startIntPartIndex) { - var scanIntPartIndex = this._currentIndex - 1; - var multiplier = 1; - while (scanIntPartIndex >= startIntPartIndex) { - integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0"); - multiplier *= 10; - } - } - - // Read the decimals. - if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") { - this._currentIndex++; - - // There must be a least one digit following the . - if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") - return undefined; - while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") - decimal += (this._string.charAt(this._currentIndex++) - "0") * (frac *= 0.1); - } - - // Read the exponent part. - if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") && (this._string.charAt(this._currentIndex + 1) != "x" && this._string.charAt(this._currentIndex + 1) != "m")) { - this._currentIndex++; - - // Read the sign of the exponent. - if (this._string.charAt(this._currentIndex) == "+") { - this._currentIndex++; - } else if (this._string.charAt(this._currentIndex) == "-") { - this._currentIndex++; - expsign = -1; - } - - // There must be an exponent. - if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") - return undefined; - - while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") { - exponent *= 10; - exponent += (this._string.charAt(this._currentIndex) - "0"); - this._currentIndex++; - } - } - - var number = integer + decimal; - number *= sign; - - if (exponent) - number *= Math.pow(10, expsign * exponent); - - if (startIndex == this._currentIndex) - return undefined; - - this._skipOptionalSpacesOrDelimiter(); - - return number; - } - - Source.prototype._parseArcFlag = function() { - if (this._currentIndex >= this._endIndex) - return undefined; - var flag = false; - var flagChar = this._string.charAt(this._currentIndex++); - if (flagChar == "0") - flag = false; - else if (flagChar == "1") - flag = true; - else - return undefined; - - this._skipOptionalSpacesOrDelimiter(); - return flag; - } - - Source.prototype.parseSegment = function() { - var lookahead = this._string[this._currentIndex]; - var command = this._pathSegTypeFromChar(lookahead); - if (command == SVGPathSeg.PATHSEG_UNKNOWN) { - // Possibly an implicit command. Not allowed if this is the first command. - if (this._previousCommand == SVGPathSeg.PATHSEG_UNKNOWN) - return null; - command = this._nextCommandHelper(lookahead, this._previousCommand); - if (command == SVGPathSeg.PATHSEG_UNKNOWN) - return null; - } else { - this._currentIndex++; - } - - this._previousCommand = command; - - switch (command) { - case SVGPathSeg.PATHSEG_MOVETO_REL: - return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber()); - case SVGPathSeg.PATHSEG_MOVETO_ABS: - return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); - case SVGPathSeg.PATHSEG_LINETO_REL: - return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber()); - case SVGPathSeg.PATHSEG_LINETO_ABS: - return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); - case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL: - return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber()); - case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS: - return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber()); - case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL: - return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber()); - case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS: - return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber()); - case SVGPathSeg.PATHSEG_CLOSEPATH: - this._skipOptionalSpaces(); - return new SVGPathSegClosePath(owningPathSegList); - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: - var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2); - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: - var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2); - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: - var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2); - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: - var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2); - case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: - var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1); - case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: - var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1); - case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: - return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber()); - case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: - return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber()); - case SVGPathSeg.PATHSEG_ARC_REL: - var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep); - case SVGPathSeg.PATHSEG_ARC_ABS: - var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()}; - return new SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep); - default: - throw "Unknown path seg type." - } - } - - var builder = new Builder(); - var source = new Source(string); - - if (!source.initialCommandIsMoveTo()) - return []; - while (source.hasMoreData()) { - var pathSeg = source.parseSegment(); - if (!pathSeg) - return []; - builder.appendSegment(pathSeg); - } - - return builder.pathSegList; - } - } - }()); - - /* jshint ignore:end */ - - if (typeof define === 'function' && define.amd) { - define("c3", ["d3"], function () { return c3; }); - } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) { - module.exports = c3; - } else { - window.c3 = c3; - } - -})(window); diff --git a/hal-core/resources/web/js/lib/c3.min.js b/hal-core/resources/web/js/lib/c3.min.js deleted file mode 100644 index 3b8fbd97..00000000 --- a/hal-core/resources/web/js/lib/c3.min.js +++ /dev/null @@ -1,6 +0,0 @@ -!function(a){"use strict";function b(a){this.owner=a}function c(a,b){if(Object.create)b.prototype=Object.create(a.prototype);else{var c=function(){};c.prototype=a.prototype,b.prototype=new c}return b.prototype.constructor=b,b}function d(a){var b=this.internal=new e(this);b.loadConfig(a),b.beforeInit(a),b.init(),b.afterInit(a),function c(a,b,d){Object.keys(a).forEach(function(e){b[e]=a[e].bind(d),Object.keys(a[e]).length>0&&c(a[e],b[e],d)})}(h,this,this)}function e(b){var c=this;c.d3=a.d3?a.d3:"undefined"!=typeof require?require("d3"):void 0,c.api=b,c.config=c.getDefaultConfig(),c.data={},c.cache={},c.axes={}}function f(a){b.call(this,a)}function g(a,b){function c(a,b){a.attr("transform",function(a){return"translate("+Math.ceil(b(a)+u)+", 0)"})}function d(a,b){a.attr("transform",function(a){return"translate(0,"+Math.ceil(b(a))+")"})}function e(a){var b=a[0],c=a[a.length-1];return c>b?[b,c]:[c,b]}function f(a){var b,c,d=[];if(a.ticks)return a.ticks.apply(a,n);for(c=a.domain(),b=Math.ceil(c[0]);b0&&d[0]>0&&d.unshift(d[0]-(d[1]-d[0])),d}function g(){var a,c=p.copy();return b.isCategory&&(a=p.domain(),c.domain([a[0],a[1]-1])),c}function h(a){var b=m?m(a):a;return"undefined"!=typeof b?b:""}function i(a){if(A)return A;var b={h:11.5,w:5.5};return a.select("text").text(h).each(function(a){var c=this.getBoundingClientRect(),d=h(a),e=c.height,f=d?c.width/d.length:void 0;e&&f&&(b.h=e,b.w=f)}).text(""),A=b,b}function j(c){return b.withoutTransition?c:a.transition(c)}function k(m){m.each(function(){function m(a,c){function d(a,b){f=void 0;for(var h=1;hc)return d(a.concat(b.substr(0,f?f:h)),b.slice(f?f+1:h));return a.concat(b)}var e,f,g,i=h(a),j=[];return"[object Array]"===Object.prototype.toString.call(i)?i:((!c||0>=c)&&(c=X?95:b.isCategory?Math.ceil(F(G[1])-F(G[0]))-12:110),d(j,i+""))}function n(a,b){var c=U.h;return 0===b&&(c="left"===q||"right"===q?-((V[a.index]-1)*(U.h/2)-3):".71em"),c}function v(a){var b=p(a)+(o?0:u);return L[0]0?"start":"end":"middle"}function x(a){return a?"rotate("+a+")":""}function y(a){return a?8*Math.sin(Math.PI*(a/180)):0}function z(a){return a?11.5-2.5*(a/15)*(a>0?1:-1):W}var A,B,C,D=k.g=a.select(this),E=this.__chart__||p,F=this.__chart__=g(),G=t?t:f(F),H=D.selectAll(".tick").data(G,F),I=H.enter().insert("g",".domain").attr("class","tick").style("opacity",1e-6),J=H.exit().remove(),K=j(H).style("opacity",1),L=p.rangeExtent?p.rangeExtent():e(p.range()),M=D.selectAll(".domain").data([0]),N=(M.enter().append("path").attr("class","domain"),j(M));I.append("line"),I.append("text");var O=I.select("line"),P=K.select("line"),Q=I.select("text"),R=K.select("text");b.isCategory?(u=Math.ceil((F(1)-F(0))/2),B=o?0:u,C=o?u:0):u=B=0;var S,T,U=i(D.select(".tick")),V=[],W=Math.max(r,0)+s,X="left"===q||"right"===q;S=H.select("text"),T=S.selectAll("tspan").data(function(a,c){var d=b.tickMultiline?m(a,b.tickWidth):[].concat(h(a));return V[c]=d.length,d.map(function(a){return{index:c,splitted:a}})}),T.enter().append("tspan"),T.exit().remove(),T.text(function(a){return a.splitted});var Y=b.tickTextRotate;switch(q){case"bottom":A=c,O.attr("y2",r),Q.attr("y",W),P.attr("x1",B).attr("x2",B).attr("y2",v),R.attr("x",0).attr("y",z(Y)).style("text-anchor",w(Y)).attr("transform",x(Y)),T.attr("x",0).attr("dy",n).attr("dx",y(Y)),N.attr("d","M"+L[0]+","+l+"V0H"+L[1]+"V"+l);break;case"top":A=c,O.attr("y2",-r),Q.attr("y",-W),P.attr("x2",0).attr("y2",-r),R.attr("x",0).attr("y",-W),S.style("text-anchor","middle"),T.attr("x",0).attr("dy","0em"),N.attr("d","M"+L[0]+","+-l+"V0H"+L[1]+"V"+-l);break;case"left":A=d,O.attr("x2",-r),Q.attr("x",-W),P.attr("x2",-r).attr("y1",C).attr("y2",C),R.attr("x",-W).attr("y",u),S.style("text-anchor","end"),T.attr("x",-W).attr("dy",n),N.attr("d","M"+-l+","+L[0]+"H0V"+L[1]+"H"+-l);break;case"right":A=d,O.attr("x2",r),Q.attr("x",W),P.attr("x2",r).attr("y2",0),R.attr("x",W).attr("y",0),S.style("text-anchor","start"),T.attr("x",W).attr("dy",n),N.attr("d","M"+l+","+L[0]+"H0V"+L[1]+"H"+l)}if(F.rangeBand){var Z=F,$=Z.rangeBand()/2;E=F=function(a){return Z(a)+$}}else E.rangeBand?E=F:J.call(A,F);I.call(A,E),K.call(A,F)})}var l,m,n,o,p=a.scale.linear(),q="bottom",r=6,s=3,t=null,u=0,v=!0;return b=b||{},l=b.withOuterTick?6:0,k.scale=function(a){return arguments.length?(p=a,k):p},k.orient=function(a){return arguments.length?(q=a in{top:1,right:1,bottom:1,left:1}?a+"":"bottom",k):q},k.tickFormat=function(a){return arguments.length?(m=a,k):m},k.tickCentered=function(a){return arguments.length?(o=a,k):o},k.tickOffset=function(){return u},k.tickInterval=function(){var a,c;return b.isCategory?a=2*u:(c=k.g.select("path.domain").node().getTotalLength()-2*l,a=c/k.g.selectAll("line").size()),a===1/0?0:a},k.ticks=function(){return arguments.length?(n=arguments,k):n},k.tickCulling=function(a){return arguments.length?(v=a,k):v},k.tickValues=function(a){if("function"==typeof a)t=function(){return a(p.domain())};else{if(!arguments.length)return t;t=a}return k},k}var h,i,j,k={version:"0.4.11"};k.generate=function(a){return new d(a)},k.chart={fn:d.prototype,internal:{fn:e.prototype,axis:{fn:f.prototype}}},h=k.chart.fn,i=k.chart.internal.fn,j=k.chart.internal.axis.fn,i.beforeInit=function(){},i.afterInit=function(){},i.init=function(){var a=this,b=a.config;if(a.initParams(),b.data_url)a.convertUrlToData(b.data_url,b.data_mimeType,b.data_headers,b.data_keys,a.initWithData);else if(b.data_json)a.initWithData(a.convertJsonToData(b.data_json,b.data_keys));else if(b.data_rows)a.initWithData(a.convertRowsToData(b.data_rows));else{if(!b.data_columns)throw Error("url or json or rows or columns is required.");a.initWithData(a.convertColumnsToData(b.data_columns))}},i.initParams=function(){var a=this,b=a.d3,c=a.config;a.clipId="c3-"+ +new Date+"-clip",a.clipIdForXAxis=a.clipId+"-xaxis",a.clipIdForYAxis=a.clipId+"-yaxis",a.clipIdForGrid=a.clipId+"-grid",a.clipIdForSubchart=a.clipId+"-subchart",a.clipPath=a.getClipPath(a.clipId),a.clipPathForXAxis=a.getClipPath(a.clipIdForXAxis),a.clipPathForYAxis=a.getClipPath(a.clipIdForYAxis),a.clipPathForGrid=a.getClipPath(a.clipIdForGrid),a.clipPathForSubchart=a.getClipPath(a.clipIdForSubchart),a.dragStart=null,a.dragging=!1,a.flowing=!1,a.cancelClick=!1,a.mouseover=!1,a.transiting=!1,a.color=a.generateColor(),a.levelColor=a.generateLevelColor(),a.dataTimeFormat=c.data_xLocaltime?b.time.format:b.time.format.utc,a.axisTimeFormat=c.axis_x_localtime?b.time.format:b.time.format.utc,a.defaultAxisTimeFormat=a.axisTimeFormat.multi([[".%L",function(a){return a.getMilliseconds()}],[":%S",function(a){return a.getSeconds()}],["%I:%M",function(a){return a.getMinutes()}],["%I %p",function(a){return a.getHours()}],["%-m/%-d",function(a){return a.getDay()&&1!==a.getDate()}],["%-m/%-d",function(a){return 1!==a.getDate()}],["%-m/%-d",function(a){return a.getMonth()}],["%Y/%-m/%-d",function(){return!0}]]),a.hiddenTargetIds=[],a.hiddenLegendIds=[],a.focusedTargetIds=[],a.defocusedTargetIds=[],a.xOrient=c.axis_rotated?"left":"bottom",a.yOrient=c.axis_rotated?c.axis_y_inner?"top":"bottom":c.axis_y_inner?"right":"left",a.y2Orient=c.axis_rotated?c.axis_y2_inner?"bottom":"top":c.axis_y2_inner?"left":"right",a.subXOrient=c.axis_rotated?"left":"bottom",a.isLegendRight="right"===c.legend_position,a.isLegendInset="inset"===c.legend_position,a.isLegendTop="top-left"===c.legend_inset_anchor||"top-right"===c.legend_inset_anchor,a.isLegendLeft="top-left"===c.legend_inset_anchor||"bottom-left"===c.legend_inset_anchor,a.legendStep=0,a.legendItemWidth=0,a.legendItemHeight=0,a.currentMaxTickWidths={x:0,y:0,y2:0},a.rotated_padding_left=30,a.rotated_padding_right=c.axis_rotated&&!c.axis_x_show?0:30,a.rotated_padding_top=5,a.withoutFadeIn={},a.intervalForObserveInserted=void 0,a.axes.subx=b.selectAll([])},i.initChartElements=function(){this.initBar&&this.initBar(),this.initLine&&this.initLine(),this.initArc&&this.initArc(),this.initGauge&&this.initGauge(),this.initText&&this.initText()},i.initWithData=function(a){var b,c,d=this,e=d.d3,g=d.config,h=!0;d.axis=new f(d),d.initPie&&d.initPie(),d.initBrush&&d.initBrush(),d.initZoom&&d.initZoom(),g.bindto?"function"==typeof g.bindto.node?d.selectChart=g.bindto:d.selectChart=e.select(g.bindto):d.selectChart=e.selectAll([]),d.selectChart.empty()&&(d.selectChart=e.select(document.createElement("div")).style("opacity",0),d.observeInserted(d.selectChart),h=!1),d.selectChart.html("").classed("c3",!0),d.data.xs={},d.data.targets=d.convertDataToTargets(a),g.data_filter&&(d.data.targets=d.data.targets.filter(g.data_filter)),g.data_hide&&d.addHiddenTargetIds(g.data_hide===!0?d.mapToIds(d.data.targets):g.data_hide),g.legend_hide&&d.addHiddenLegendIds(g.legend_hide===!0?d.mapToIds(d.data.targets):g.legend_hide),d.hasType("gauge")&&(g.legend_show=!1),d.updateSizes(),d.updateScales(),d.x.domain(e.extent(d.getXDomain(d.data.targets))),d.y.domain(d.getYDomain(d.data.targets,"y")),d.y2.domain(d.getYDomain(d.data.targets,"y2")),d.subX.domain(d.x.domain()),d.subY.domain(d.y.domain()),d.subY2.domain(d.y2.domain()),d.orgXDomain=d.x.domain(),d.brush&&d.brush.scale(d.subX),g.zoom_enabled&&d.zoom.scale(d.x),d.svg=d.selectChart.append("svg").style("overflow","hidden").on("mouseenter",function(){return g.onmouseover.call(d)}).on("mouseleave",function(){return g.onmouseout.call(d)}),d.config.svg_classname&&d.svg.attr("class",d.config.svg_classname),b=d.svg.append("defs"),d.clipChart=d.appendClip(b,d.clipId),d.clipXAxis=d.appendClip(b,d.clipIdForXAxis),d.clipYAxis=d.appendClip(b,d.clipIdForYAxis),d.clipGrid=d.appendClip(b,d.clipIdForGrid),d.clipSubchart=d.appendClip(b,d.clipIdForSubchart),d.updateSvgSize(),c=d.main=d.svg.append("g").attr("transform",d.getTranslate("main")),d.initSubchart&&d.initSubchart(),d.initTooltip&&d.initTooltip(),d.initLegend&&d.initLegend(),d.initTitle&&d.initTitle(),c.append("text").attr("class",l.text+" "+l.empty).attr("text-anchor","middle").attr("dominant-baseline","middle"),d.initRegion(),d.initGrid(),c.append("g").attr("clip-path",d.clipPath).attr("class",l.chart),g.grid_lines_front&&d.initGridLines(),d.initEventRect(),d.initChartElements(),c.insert("rect",g.zoom_privileged?null:"g."+l.regions).attr("class",l.zoomRect).attr("width",d.width).attr("height",d.height).style("opacity",0).on("dblclick.zoom",null),g.axis_x_extent&&d.brush.extent(d.getDefaultExtent()),d.axis.init(),d.updateTargets(d.data.targets),h&&(d.updateDimension(),d.config.oninit.call(d),d.redraw({withTransition:!1,withTransform:!0,withUpdateXDomain:!0,withUpdateOrgXDomain:!0,withTransitionForAxis:!1})),d.bindResize(),d.api.element=d.selectChart.node()},i.smoothLines=function(a,b){var c=this;"grid"===b&&a.each(function(){var a=c.d3.select(this),b=a.attr("x1"),d=a.attr("x2"),e=a.attr("y1"),f=a.attr("y2");a.attr({x1:Math.ceil(b),x2:Math.ceil(d),y1:Math.ceil(e),y2:Math.ceil(f)})})},i.updateSizes=function(){var a=this,b=a.config,c=a.legend?a.getLegendHeight():0,d=a.legend?a.getLegendWidth():0,e=a.isLegendRight||a.isLegendInset?0:c,f=a.hasArcType(),g=b.axis_rotated||f?0:a.getHorizontalAxisHeight("x"),h=b.subchart_show&&!f?b.subchart_size_height+g:0;a.currentWidth=a.getCurrentWidth(),a.currentHeight=a.getCurrentHeight(),a.margin=b.axis_rotated?{top:a.getHorizontalAxisHeight("y2")+a.getCurrentPaddingTop(),right:f?0:a.getCurrentPaddingRight(),bottom:a.getHorizontalAxisHeight("y")+e+a.getCurrentPaddingBottom(),left:h+(f?0:a.getCurrentPaddingLeft())}:{top:4+a.getCurrentPaddingTop(),right:f?0:a.getCurrentPaddingRight(),bottom:g+h+e+a.getCurrentPaddingBottom(),left:f?0:a.getCurrentPaddingLeft()},a.margin2=b.axis_rotated?{top:a.margin.top,right:NaN,bottom:20+e,left:a.rotated_padding_left}:{top:a.currentHeight-h-e,right:NaN,bottom:g+e,left:a.margin.left},a.margin3={top:0,right:NaN,bottom:0,left:0},a.updateSizeForLegend&&a.updateSizeForLegend(c,d),a.width=a.currentWidth-a.margin.left-a.margin.right,a.height=a.currentHeight-a.margin.top-a.margin.bottom,a.width<0&&(a.width=0),a.height<0&&(a.height=0),a.width2=b.axis_rotated?a.margin.left-a.rotated_padding_left-a.rotated_padding_right:a.width,a.height2=b.axis_rotated?a.height:a.currentHeight-a.margin2.top-a.margin2.bottom,a.width2<0&&(a.width2=0),a.height2<0&&(a.height2=0),a.arcWidth=a.width-(a.isLegendRight?d+10:0),a.arcHeight=a.height-(a.isLegendRight?0:10),a.hasType("gauge")&&!b.gauge_fullCircle&&(a.arcHeight+=a.height-a.getGaugeLabelHeight()),a.updateRadius&&a.updateRadius(),a.isLegendRight&&f&&(a.margin3.left=a.arcWidth/2+1.1*a.radiusExpanded)},i.updateTargets=function(a){var b=this;b.updateTargetsForText(a),b.updateTargetsForBar(a),b.updateTargetsForLine(a),b.hasArcType()&&b.updateTargetsForArc&&b.updateTargetsForArc(a),b.updateTargetsForSubchart&&b.updateTargetsForSubchart(a),b.showTargets()},i.showTargets=function(){var a=this;a.svg.selectAll("."+l.target).filter(function(b){return a.isTargetToShow(b.id)}).transition().duration(a.config.transition_duration).style("opacity",1)},i.redraw=function(a,b){var c,d,e,f,g,h,i,j,k,m,n,o,p,q,r,s,t,u,v,x,y,z,A,B,C,D,E,F,G,H=this,I=H.main,J=H.d3,K=H.config,L=H.getShapeIndices(H.isAreaType),M=H.getShapeIndices(H.isBarType),N=H.getShapeIndices(H.isLineType),O=H.hasArcType(),P=H.filterTargetsToShow(H.data.targets),Q=H.xv.bind(H);if(a=a||{},c=w(a,"withY",!0),d=w(a,"withSubchart",!0),e=w(a,"withTransition",!0),h=w(a,"withTransform",!1),i=w(a,"withUpdateXDomain",!1),j=w(a,"withUpdateOrgXDomain",!1),k=w(a,"withTrimXDomain",!0),p=w(a,"withUpdateXAxis",i),m=w(a,"withLegend",!1),n=w(a,"withEventRect",!0),o=w(a,"withDimension",!0),f=w(a,"withTransitionForExit",e),g=w(a,"withTransitionForAxis",e),v=e?K.transition_duration:0,x=f?v:0,y=g?v:0,b=b||H.axis.generateTransitions(y),m&&K.legend_show?H.updateLegend(H.mapToIds(H.data.targets),a,b):o&&H.updateDimension(!0),H.isCategorized()&&0===P.length&&H.x.domain([0,H.axes.x.selectAll(".tick").size()]),P.length?(H.updateXDomain(P,i,j,k),K.axis_x_tick_values||(B=H.axis.updateXAxisTickValues(P))):(H.xAxis.tickValues([]),H.subXAxis.tickValues([])),K.zoom_rescale&&!a.flow&&(E=H.x.orgDomain()),H.y.domain(H.getYDomain(P,"y",E)),H.y2.domain(H.getYDomain(P,"y2",E)),!K.axis_y_tick_values&&K.axis_y_tick_count&&H.yAxis.tickValues(H.axis.generateTickValues(H.y.domain(),K.axis_y_tick_count)),!K.axis_y2_tick_values&&K.axis_y2_tick_count&&H.y2Axis.tickValues(H.axis.generateTickValues(H.y2.domain(),K.axis_y2_tick_count)),H.axis.redraw(b,O),H.axis.updateLabels(e),(i||p)&&P.length)if(K.axis_x_tick_culling&&B){for(C=1;C=0&&J.select(this).style("display",b%D?"none":"block")})}else H.svg.selectAll("."+l.axisX+" .tick text").style("display","block");q=H.generateDrawArea?H.generateDrawArea(L,!1):void 0,r=H.generateDrawBar?H.generateDrawBar(M):void 0,s=H.generateDrawLine?H.generateDrawLine(N,!1):void 0,t=H.generateXYForText(L,M,N,!0),u=H.generateXYForText(L,M,N,!1),c&&(H.subY.domain(H.getYDomain(P,"y")),H.subY2.domain(H.getYDomain(P,"y2"))),H.updateXgridFocus(),I.select("text."+l.text+"."+l.empty).attr("x",H.width/2).attr("y",H.height/2).text(K.data_empty_label_text).transition().style("opacity",P.length?0:1),H.updateGrid(v),H.updateRegion(v),H.updateBar(x),H.updateLine(x),H.updateArea(x),H.updateCircle(),H.hasDataLabel()&&H.updateText(x),H.redrawTitle&&H.redrawTitle(),H.redrawArc&&H.redrawArc(v,x,h),H.redrawSubchart&&H.redrawSubchart(d,b,v,x,L,M,N),I.selectAll("."+l.selectedCircles).filter(H.isBarType.bind(H)).selectAll("circle").remove(),K.interaction_enabled&&!a.flow&&n&&(H.redrawEventRect(),H.updateZoom&&H.updateZoom()),H.updateCircleY(),F=(H.config.axis_rotated?H.circleY:H.circleX).bind(H),G=(H.config.axis_rotated?H.circleX:H.circleY).bind(H),a.flow&&(A=H.generateFlow({targets:P,flow:a.flow,duration:a.flow.duration,drawBar:r,drawLine:s,drawArea:q,cx:F,cy:G,xv:Q,xForText:t,yForText:u})),(v||A)&&H.isTabVisible()?J.transition().duration(v).each(function(){var b=[];[H.redrawBar(r,!0),H.redrawLine(s,!0),H.redrawArea(q,!0),H.redrawCircle(F,G,!0),H.redrawText(t,u,a.flow,!0),H.redrawRegion(!0),H.redrawGrid(!0)].forEach(function(a){a.forEach(function(a){b.push(a)})}),z=H.generateWait(),b.forEach(function(a){z.add(a)})}).call(z,function(){A&&A(),K.onrendered&&K.onrendered.call(H)}):(H.redrawBar(r),H.redrawLine(s),H.redrawArea(q),H.redrawCircle(F,G),H.redrawText(t,u,a.flow),H.redrawRegion(),H.redrawGrid(),K.onrendered&&K.onrendered.call(H)),H.mapToIds(H.data.targets).forEach(function(a){H.withoutFadeIn[a]=!0})},i.updateAndRedraw=function(a){var b,c=this,d=c.config;a=a||{},a.withTransition=w(a,"withTransition",!0),a.withTransform=w(a,"withTransform",!1),a.withLegend=w(a,"withLegend",!1),a.withUpdateXDomain=!0,a.withUpdateOrgXDomain=!0,a.withTransitionForExit=!1,a.withTransitionForTransform=w(a,"withTransitionForTransform",a.withTransition),c.updateSizes(),a.withLegend&&d.legend_show||(b=c.axis.generateTransitions(a.withTransitionForAxis?d.transition_duration:0),c.updateScales(),c.updateSvgSize(),c.transformAll(a.withTransitionForTransform,b)),c.redraw(a,b)},i.redrawWithoutRescale=function(){this.redraw({withY:!1,withSubchart:!1,withEventRect:!1,withTransitionForAxis:!1})},i.isTimeSeries=function(){return"timeseries"===this.config.axis_x_type},i.isCategorized=function(){return this.config.axis_x_type.indexOf("categor")>=0},i.isCustomX=function(){var a=this,b=a.config;return!a.isTimeSeries()&&(b.data_x||v(b.data_xs))},i.isTimeSeriesY=function(){return"timeseries"===this.config.axis_y_type},i.getTranslate=function(a){var b,c,d=this,e=d.config;return"main"===a?(b=s(d.margin.left),c=s(d.margin.top)):"context"===a?(b=s(d.margin2.left),c=s(d.margin2.top)):"legend"===a?(b=d.margin3.left,c=d.margin3.top):"x"===a?(b=0,c=e.axis_rotated?0:d.height):"y"===a?(b=0,c=e.axis_rotated?d.height:0):"y2"===a?(b=e.axis_rotated?0:d.width,c=e.axis_rotated?1:0):"subx"===a?(b=0,c=e.axis_rotated?0:d.height2):"arc"===a&&(b=d.arcWidth/2,c=d.arcHeight/2),"translate("+b+","+c+")"},i.initialOpacity=function(a){return null!==a.value&&this.withoutFadeIn[a.id]?1:0},i.initialOpacityForCircle=function(a){return null!==a.value&&this.withoutFadeIn[a.id]?this.opacityForCircle(a):0},i.opacityForCircle=function(a){var b=this.config.point_show?1:0;return m(a.value)?this.isScatterType(a)?.5:b:0},i.opacityForText=function(){return this.hasDataLabel()?1:0},i.xx=function(a){return a?this.x(a.x):null},i.xv=function(a){var b=this,c=a.value;return b.isTimeSeries()?c=b.parseDate(a.value):b.isCategorized()&&"string"==typeof a.value&&(c=b.config.axis_x_categories.indexOf(a.value)),Math.ceil(b.x(c))},i.yv=function(a){var b=this,c=a.axis&&"y2"===a.axis?b.y2:b.y;return Math.ceil(c(a.value))},i.subxx=function(a){return a?this.subX(a.x):null},i.transformMain=function(a,b){var c,d,e,f=this;b&&b.axisX?c=b.axisX:(c=f.main.select("."+l.axisX),a&&(c=c.transition())),b&&b.axisY?d=b.axisY:(d=f.main.select("."+l.axisY),a&&(d=d.transition())),b&&b.axisY2?e=b.axisY2:(e=f.main.select("."+l.axisY2),a&&(e=e.transition())),(a?f.main.transition():f.main).attr("transform",f.getTranslate("main")),c.attr("transform",f.getTranslate("x")),d.attr("transform",f.getTranslate("y")),e.attr("transform",f.getTranslate("y2")),f.main.select("."+l.chartArcs).attr("transform",f.getTranslate("arc"))},i.transformAll=function(a,b){var c=this;c.transformMain(a,b),c.config.subchart_show&&c.transformContext(a,b),c.legend&&c.transformLegend(a)},i.updateSvgSize=function(){var a=this,b=a.svg.select(".c3-brush .background");a.svg.attr("width",a.currentWidth).attr("height",a.currentHeight),a.svg.selectAll(["#"+a.clipId,"#"+a.clipIdForGrid]).select("rect").attr("width",a.width).attr("height",a.height),a.svg.select("#"+a.clipIdForXAxis).select("rect").attr("x",a.getXAxisClipX.bind(a)).attr("y",a.getXAxisClipY.bind(a)).attr("width",a.getXAxisClipWidth.bind(a)).attr("height",a.getXAxisClipHeight.bind(a)),a.svg.select("#"+a.clipIdForYAxis).select("rect").attr("x",a.getYAxisClipX.bind(a)).attr("y",a.getYAxisClipY.bind(a)).attr("width",a.getYAxisClipWidth.bind(a)).attr("height",a.getYAxisClipHeight.bind(a)),a.svg.select("#"+a.clipIdForSubchart).select("rect").attr("width",a.width).attr("height",b.size()?b.attr("height"):0),a.svg.select("."+l.zoomRect).attr("width",a.width).attr("height",a.height),a.selectChart.style("max-height",a.currentHeight+"px")},i.updateDimension=function(a){var b=this;a||(b.config.axis_rotated?(b.axes.x.call(b.xAxis),b.axes.subx.call(b.subXAxis)):(b.axes.y.call(b.yAxis),b.axes.y2.call(b.y2Axis))),b.updateSizes(),b.updateScales(),b.updateSvgSize(),b.transformAll(!1)},i.observeInserted=function(b){var c,d=this;return"undefined"==typeof MutationObserver?void a.console.error("MutationObserver not defined."):(c=new MutationObserver(function(e){e.forEach(function(e){"childList"===e.type&&e.previousSibling&&(c.disconnect(),d.intervalForObserveInserted=a.setInterval(function(){b.node().parentNode&&(a.clearInterval(d.intervalForObserveInserted),d.updateDimension(),d.brush&&d.brush.update(),d.config.oninit.call(d),d.redraw({withTransform:!0,withUpdateXDomain:!0,withUpdateOrgXDomain:!0,withTransition:!1,withTransitionForTransform:!1,withLegend:!0}),b.transition().style("opacity",1))},10))})}),void c.observe(b.node(),{attributes:!0,childList:!0,characterData:!0}))},i.bindResize=function(){var b=this,c=b.config;if(b.resizeFunction=b.generateResize(),b.resizeFunction.add(function(){c.onresize.call(b)}),c.resize_auto&&b.resizeFunction.add(function(){void 0!==b.resizeTimeout&&a.clearTimeout(b.resizeTimeout),b.resizeTimeout=a.setTimeout(function(){delete b.resizeTimeout,b.api.flush()},100)}),b.resizeFunction.add(function(){c.onresized.call(b)}),a.attachEvent)a.attachEvent("onresize",b.resizeFunction);else if(a.addEventListener)a.addEventListener("resize",b.resizeFunction,!1);else{var d=a.onresize;d?d.add&&d.remove||(d=b.generateResize(),d.add(a.onresize)):d=b.generateResize(),d.add(b.resizeFunction),a.onresize=d}},i.generateResize=function(){function a(){b.forEach(function(a){a()})}var b=[];return a.add=function(a){b.push(a)},a.remove=function(a){for(var c=0;c0)for(g=h.hasNegativeValueInTargets(a),b=0;b=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=0>a?a:0}),c=1;c0||(k[d][b]+=+a)});return h.d3.min(Object.keys(k).map(function(a){return h.d3.min(k[a])}))},i.getYDomainMax=function(a){var b,c,d,e,f,g,h=this,i=h.config,j=h.mapToIds(a),k=h.getValuesAsIdKeyed(a);if(i.data_groups.length>0)for(g=h.hasPositiveValueInTargets(a),b=0;b=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=a>0?a:0}),c=1;c+a||(k[d][b]+=+a)});return h.d3.max(Object.keys(k).map(function(a){return h.d3.max(k[a])}))},i.getYDomain=function(a,b,c){var d,e,f,g,h,i,j,k,l,n,o,p=this,q=p.config,r=a.filter(function(a){return p.axis.getId(a.id)===b}),s=c?p.filterByXDomain(r,c):r,u="y2"===b?q.axis_y2_min:q.axis_y_min,w="y2"===b?q.axis_y2_max:q.axis_y_max,x=p.getYDomainMin(s),y=p.getYDomainMax(s),z="y2"===b?q.axis_y2_center:q.axis_y_center,A=p.hasType("bar",s)&&q.bar_zerobased||p.hasType("area",s)&&q.area_zerobased,B="y2"===b?q.axis_y2_inverted:q.axis_y_inverted,C=p.hasDataLabel()&&q.axis_rotated,D=p.hasDataLabel()&&!q.axis_rotated;return x=m(u)?u:m(w)?w>x?x:w-10:x,y=m(w)?w:m(u)?y>u?y:u+10:y,0===s.length?"y2"===b?p.y2.domain():p.y.domain():(isNaN(x)&&(x=0),isNaN(y)&&(y=x),x===y&&(0>x?y=0:x=0),n=x>=0&&y>=0,o=0>=x&&0>=y,(m(u)&&n||m(w)&&o)&&(A=!1),A&&(n&&(x=0),o&&(y=0)),e=Math.abs(y-x),f=g=h=.1*e,"undefined"!=typeof z&&(i=Math.max(Math.abs(x),Math.abs(y)),y=z+i,x=z-i),C?(j=p.getDataLabelLength(x,y,"width"),k=t(p.y.range()),l=[j[0]/k,j[1]/k], -g+=e*(l[1]/(1-l[0]-l[1])),h+=e*(l[0]/(1-l[0]-l[1]))):D&&(j=p.getDataLabelLength(x,y,"height"),g+=p.axis.convertPixelsToAxisPadding(j[1],e),h+=p.axis.convertPixelsToAxisPadding(j[0],e)),"y"===b&&v(q.axis_y_padding)&&(g=p.axis.getPadding(q.axis_y_padding,"top",g,e),h=p.axis.getPadding(q.axis_y_padding,"bottom",h,e)),"y2"===b&&v(q.axis_y2_padding)&&(g=p.axis.getPadding(q.axis_y2_padding,"top",g,e),h=p.axis.getPadding(q.axis_y2_padding,"bottom",h,e)),A&&(n&&(h=x),o&&(g=-y)),d=[x-h,y+g],B?d.reverse():d)},i.getXDomainMin=function(a){var b=this,c=b.config;return q(c.axis_x_min)?b.isTimeSeries()?this.parseDate(c.axis_x_min):c.axis_x_min:b.d3.min(a,function(a){return b.d3.min(a.values,function(a){return a.x})})},i.getXDomainMax=function(a){var b=this,c=b.config;return q(c.axis_x_max)?b.isTimeSeries()?this.parseDate(c.axis_x_max):c.axis_x_max:b.d3.max(a,function(a){return b.d3.max(a.values,function(a){return a.x})})},i.getXDomainPadding=function(a){var b,c,d,e,f=this,g=f.config,h=a[1]-a[0];return f.isCategorized()?c=0:f.hasType("bar")?(b=f.getMaxDataCount(),c=b>1?h/(b-1)/2:.5):c=.01*h,"object"==typeof g.axis_x_padding&&v(g.axis_x_padding)?(d=m(g.axis_x_padding.left)?g.axis_x_padding.left:c,e=m(g.axis_x_padding.right)?g.axis_x_padding.right:c):d=e="number"==typeof g.axis_x_padding?g.axis_x_padding:c,{left:d,right:e}},i.getXDomain=function(a){var b=this,c=[b.getXDomainMin(a),b.getXDomainMax(a)],d=c[0],e=c[1],f=b.getXDomainPadding(c),g=0,h=0;return d-e!==0||b.isCategorized()||(b.isTimeSeries()?(d=new Date(.5*d.getTime()),e=new Date(1.5*e.getTime())):(d=0===d?1:.5*d,e=0===e?-1:1.5*e)),(d||0===d)&&(g=b.isTimeSeries()?new Date(d.getTime()-f.left):d-f.left),(e||0===e)&&(h=b.isTimeSeries()?new Date(e.getTime()+f.right):e+f.right),[g,h]},i.updateXDomain=function(a,b,c,d,e){var f=this,g=f.config;return c&&(f.x.domain(e?e:f.d3.extent(f.getXDomain(a))),f.orgXDomain=f.x.domain(),g.zoom_enabled&&f.zoom.scale(f.x).updateScaleExtent(),f.subX.domain(f.x.domain()),f.brush&&f.brush.scale(f.subX)),b&&(f.x.domain(e?e:!f.brush||f.brush.empty()?f.orgXDomain:f.brush.extent()),g.zoom_enabled&&f.zoom.scale(f.x).updateScaleExtent()),d&&f.x.domain(f.trimXDomain(f.x.orgDomain())),f.x.domain()},i.trimXDomain=function(a){var b=this.getZoomDomain(),c=b[0],d=b[1];return a[0]<=c&&(a[1]=+a[1]+(c-a[0]),a[0]=c),d<=a[1]&&(a[0]=+a[0]-(a[1]-d),a[1]=d),a},i.isX=function(a){var b=this,c=b.config;return c.data_x&&a===c.data_x||v(c.data_xs)&&x(c.data_xs,a)},i.isNotX=function(a){return!this.isX(a)},i.getXKey=function(a){var b=this,c=b.config;return c.data_x?c.data_x:v(c.data_xs)?c.data_xs[a]:null},i.getXValuesOfXKey=function(a,b){var c,d=this,e=b&&v(b)?d.mapToIds(b):[];return e.forEach(function(b){d.getXKey(b)===a&&(c=d.data.xs[b])}),c},i.getIndexByX=function(a){var b=this,c=b.filterByX(b.data.targets,a);return c.length?c[0].index:null},i.getXValue=function(a,b){var c=this;return a in c.data.xs&&c.data.xs[a]&&m(c.data.xs[a][b])?c.data.xs[a][b]:b},i.getOtherTargetXs=function(){var a=this,b=Object.keys(a.data.xs);return b.length?a.data.xs[b[0]]:null},i.getOtherTargetX=function(a){var b=this.getOtherTargetXs();return b&&a1},i.isMultipleX=function(){return v(this.config.data_xs)||!this.config.data_xSort||this.hasType("scatter")},i.addName=function(a){var b,c=this;return a&&(b=c.config.data_names[a.id],a.name=void 0!==b?b:a.id),a},i.getValueOnIndex=function(a,b){var c=a.filter(function(a){return a.index===b});return c.length?c[0]:null},i.updateTargetX=function(a,b){var c=this;a.forEach(function(a){a.values.forEach(function(d,e){d.x=c.generateTargetX(b[e],a.id,e)}),c.data.xs[a.id]=b})},i.updateTargetXs=function(a,b){var c=this;a.forEach(function(a){b[a.id]&&c.updateTargetX([a],b[a.id])})},i.generateTargetX=function(a,b,c){var d,e=this;return d=e.isTimeSeries()?a?e.parseDate(a):e.parseDate(e.getXValue(b,c)):e.isCustomX()&&!e.isCategorized()?m(a)?+a:e.getXValue(b,c):c},i.cloneTarget=function(a){return{id:a.id,id_org:a.id_org,values:a.values.map(function(a){return{x:a.x,value:a.value,id:a.id}})}},i.updateXs=function(){var a=this;a.data.targets.length&&(a.xs=[],a.data.targets[0].values.forEach(function(b){a.xs[b.index]=b.x}))},i.getPrevX=function(a){var b=this.xs[a-1];return"undefined"!=typeof b?b:null},i.getNextX=function(a){var b=this.xs[a+1];return"undefined"!=typeof b?b:null},i.getMaxDataCount=function(){var a=this;return a.d3.max(a.data.targets,function(a){return a.values.length})},i.getMaxDataCountTarget=function(a){var b,c=a.length,d=0;return c>1?a.forEach(function(a){a.values.length>d&&(b=a,d=a.values.length)}):b=c?a[0]:null,b},i.getEdgeX=function(a){var b=this;return a.length?[b.d3.min(a,function(a){return a.values[0].x}),b.d3.max(a,function(a){return a.values[a.values.length-1].x})]:[0,0]},i.mapToIds=function(a){return a.map(function(a){return a.id})},i.mapToTargetIds=function(a){var b=this;return a?[].concat(a):b.mapToIds(b.data.targets)},i.hasTarget=function(a,b){var c,d=this.mapToIds(a);for(c=0;ca?-1:a>b?1:a>=b?0:NaN})},i.addHiddenTargetIds=function(a){this.hiddenTargetIds=this.hiddenTargetIds.concat(a)},i.removeHiddenTargetIds=function(a){this.hiddenTargetIds=this.hiddenTargetIds.filter(function(b){return a.indexOf(b)<0})},i.addHiddenLegendIds=function(a){this.hiddenLegendIds=this.hiddenLegendIds.concat(a)},i.removeHiddenLegendIds=function(a){this.hiddenLegendIds=this.hiddenLegendIds.filter(function(b){return a.indexOf(b)<0})},i.getValuesAsIdKeyed=function(a){var b={};return a.forEach(function(a){b[a.id]=[],a.values.forEach(function(c){b[a.id].push(c.value)})}),b},i.checkValueInTargets=function(a,b){var c,d,e,f=Object.keys(a);for(c=0;ca})},i.hasPositiveValueInTargets=function(a){return this.checkValueInTargets(a,function(a){return a>0})},i.isOrderDesc=function(){var a=this.config;return"string"==typeof a.data_order&&"desc"===a.data_order.toLowerCase()},i.isOrderAsc=function(){var a=this.config;return"string"==typeof a.data_order&&"asc"===a.data_order.toLowerCase()},i.orderTargets=function(a){var b=this,c=b.config,d=b.isOrderAsc(),e=b.isOrderDesc();return d||e?a.sort(function(a,b){var c=function(a,b){return a+Math.abs(b.value)},e=a.values.reduce(c,0),f=b.values.reduce(c,0);return d?f-e:e-f}):n(c.data_order)&&a.sort(c.data_order),a},i.filterByX=function(a,b){return this.d3.merge(a.map(function(a){return a.values})).filter(function(a){return a.x-b===0})},i.filterRemoveNull=function(a){return a.filter(function(a){return m(a.value)})},i.filterByXDomain=function(a,b){return a.map(function(a){return{id:a.id,id_org:a.id_org,values:a.values.filter(function(a){return b[0]<=a.x&&a.x<=b[1]})}})},i.hasDataLabel=function(){var a=this.config;return"boolean"==typeof a.data_labels&&a.data_labels?!0:!("object"!=typeof a.data_labels||!v(a.data_labels))},i.getDataLabelLength=function(a,b,c){var d=this,e=[0,0],f=1.3;return d.selectChart.select("svg").selectAll(".dummy").data([a,b]).enter().append("text").text(function(a){return d.dataLabelFormat(a.id)(a)}).each(function(a,b){e[b]=this.getBoundingClientRect()[c]*f}).remove(),e},i.isNoneArc=function(a){return this.hasTarget(this.data.targets,a.id)},i.isArc=function(a){return"data"in a&&this.hasTarget(this.data.targets,a.data.id)},i.findSameXOfValues=function(a,b){var c,d=a[b].x,e=[];for(c=b-1;c>=0&&d===a[c].x;c--)e.push(a[c]);for(c=b;cf&&(e=f,c=a)}),c},i.dist=function(a,b){var c=this,d=c.config,e=d.axis_rotated?1:0,f=d.axis_rotated?0:1,g=c.circleY(a,a.index),h=c.x(a.x);return Math.sqrt(Math.pow(h-b[e],2)+Math.pow(g-b[f],2))},i.convertValuesToStep=function(a){var b,c=[].concat(a);if(!this.isCategorized())return a;for(b=a.length+1;b>0;b--)c[b]=c[b-1];return c[0]={x:c[0].x-1,value:c[0].value,id:c[0].id},c[a.length+1]={x:c[a.length].x+1,value:c[a.length].value,id:c[a.length].id},c},i.updateDataAttributes=function(a,b){var c=this,d=c.config,e=d["data_"+a];return"undefined"==typeof b?e:(Object.keys(b).forEach(function(a){e[a]=b[a]}),c.redraw({withLegend:!0}),e)},i.convertUrlToData=function(a,b,c,d,e){var f=this,g=b?b:"csv",h=f.d3.xhr(a);c&&Object.keys(c).forEach(function(a){h.header(a,c[a])}),h.get(function(a,b){var c;if(!b)throw new Error(a.responseURL+" "+a.status+" ("+a.statusText+")");c="json"===g?f.convertJsonToData(JSON.parse(b.response),d):"tsv"===g?f.convertTsvToData(b.response):f.convertCsvToData(b.response),e.call(f,c)})},i.convertXsvToData=function(a,b){var c,d=b.parseRows(a);return 1===d.length?(c=[{}],d[0].forEach(function(a){c[0][a]=null})):c=b.parse(a),c},i.convertCsvToData=function(a){return this.convertXsvToData(a,this.d3.csv)},i.convertTsvToData=function(a){return this.convertXsvToData(a,this.d3.tsv)},i.convertJsonToData=function(a,b){var c,d,e=this,f=[];return b?(b.x?(c=b.value.concat(b.x),e.config.data_x=b.x):c=b.value,f.push(c),a.forEach(function(a){var b=[];c.forEach(function(c){var d=e.findValueInJson(a,c);p(d)&&(d=null),b.push(d)}),f.push(b)}),d=e.convertRowsToData(f)):(Object.keys(a).forEach(function(b){f.push([b].concat(a[b]))}),d=e.convertColumnsToData(f)),d},i.findValueInJson=function(a,b){b=b.replace(/\[(\w+)\]/g,".$1"),b=b.replace(/^\./,"");for(var c=b.split("."),d=0;d=0?d.data.xs[c]=(b&&d.data.xs[c]?d.data.xs[c]:[]).concat(a.map(function(a){return a[f]}).filter(m).map(function(a,b){return d.generateTargetX(a,c,b)})):e.data_x?d.data.xs[c]=d.getOtherTargetXs():v(e.data_xs)&&(d.data.xs[c]=d.getXValuesOfXKey(f,d.data.targets)):d.data.xs[c]=a.map(function(a,b){return b})}),f.forEach(function(a){if(!d.data.xs[a])throw new Error('x is not defined for id = "'+a+'".')}),c=f.map(function(b,c){var f=e.data_idConverter(b);return{id:f,id_org:b,values:a.map(function(a,g){var h,i=d.getXKey(b),j=a[i],k=null===a[b]||isNaN(a[b])?null:+a[b];return d.isCustomX()&&d.isCategorized()&&0===c&&!p(j)?(0===c&&0===g&&(e.axis_x_categories=[]),h=e.axis_x_categories.indexOf(j),-1===h&&(h=e.axis_x_categories.length,e.axis_x_categories.push(j))):h=d.generateTargetX(j,b,g),(p(a[b])||d.data.xs[b].length<=g)&&(h=void 0),{x:h,value:k,id:f}}).filter(function(a){return q(a.x)})}}),c.forEach(function(a){var b;e.data_xSort&&(a.values=a.values.sort(function(a,b){var c=a.x||0===a.x?a.x:1/0,d=b.x||0===b.x?b.x:1/0;return c-d})),b=0,a.values.forEach(function(a){a.index=b++}),d.data.xs[a.id].sort(function(a,b){return a-b})}),d.hasNegativeValue=d.hasNegativeValueInTargets(c),d.hasPositiveValue=d.hasPositiveValueInTargets(c),e.data_type&&d.setTargetType(d.mapToIds(c).filter(function(a){return!(a in e.data_types)}),e.data_type),c.forEach(function(a){d.addCache(a.id_org,a)}),c},i.load=function(a,b){var c=this;a&&(b.filter&&(a=a.filter(b.filter)),(b.type||b.types)&&a.forEach(function(a){var d=b.types&&b.types[a.id]?b.types[a.id]:b.type;c.setTargetType(a.id,d)}),c.data.targets.forEach(function(b){for(var c=0;c0?c:320/(a.hasType("gauge")&&!b.gauge_fullCircle?2:1)},i.getCurrentPaddingTop=function(){var a=this,b=a.config,c=m(b.padding_top)?b.padding_top:0;return a.title&&a.title.node()&&(c+=a.getTitlePadding()),c},i.getCurrentPaddingBottom=function(){var a=this.config;return m(a.padding_bottom)?a.padding_bottom:0},i.getCurrentPaddingLeft=function(a){var b=this,c=b.config;return m(c.padding_left)?c.padding_left:c.axis_rotated?c.axis_x_show?Math.max(r(b.getAxisWidthByAxisId("x",a)),40):1:!c.axis_y_show||c.axis_y_inner?b.axis.getYAxisLabelPosition().isOuter?30:1:r(b.getAxisWidthByAxisId("y",a))},i.getCurrentPaddingRight=function(){var a=this,b=a.config,c=10,d=a.isLegendRight?a.getLegendWidth()+20:0;return m(b.padding_right)?b.padding_right+1:b.axis_rotated?c+d:!b.axis_y2_show||b.axis_y2_inner?2+d+(a.axis.getY2AxisLabelPosition().isOuter?20:0):r(a.getAxisWidthByAxisId("y2"))+d},i.getParentRectValue=function(a){for(var b,c=this.selectChart.node();c&&"BODY"!==c.tagName;){try{b=c.getBoundingClientRect()[a]}catch(d){"width"===a&&(b=c.offsetWidth)}if(b)break;c=c.parentNode}return b},i.getParentWidth=function(){return this.getParentRectValue("width")},i.getParentHeight=function(){var a=this.selectChart.style("height");return a.indexOf("px")>0?+a.replace("px",""):0},i.getSvgLeft=function(a){var b=this,c=b.config,d=c.axis_rotated||!c.axis_rotated&&!c.axis_y_inner,e=c.axis_rotated?l.axisX:l.axisY,f=b.main.select("."+e).node(),g=f&&d?f.getBoundingClientRect():{right:0},h=b.selectChart.node().getBoundingClientRect(),i=b.hasArcType(),j=g.right-h.left-(i?0:b.getCurrentPaddingLeft(a));return j>0?j:0},i.getAxisWidthByAxisId=function(a,b){var c=this,d=c.axis.getLabelPositionById(a);return c.axis.getMaxTickWidth(a,b)+(d.isInner?20:40)},i.getHorizontalAxisHeight=function(a){var b=this,c=b.config,d=30;return"x"!==a||c.axis_x_show?"x"===a&&c.axis_x_height?c.axis_x_height:"y"!==a||c.axis_y_show?"y2"!==a||c.axis_y2_show?("x"===a&&!c.axis_rotated&&c.axis_x_tick_rotate&&(d=30+b.axis.getMaxTickWidth(a)*Math.cos(Math.PI*(90-c.axis_x_tick_rotate)/180)),"y"===a&&c.axis_rotated&&c.axis_y_tick_rotate&&(d=30+b.axis.getMaxTickWidth(a)*Math.cos(Math.PI*(90-c.axis_y_tick_rotate)/180)),d+(b.axis.getLabelPositionById(a).isInner?0:10)+("y2"===a?-10:0)):b.rotated_padding_top:!c.legend_show||b.isLegendRight||b.isLegendInset?1:10:8},i.getEventRectWidth=function(){return Math.max(0,this.xAxis.tickInterval())},i.getShapeIndices=function(a){var b,c,d=this,e=d.config,f={},g=0;return d.filterTargetsToShow(d.data.targets.filter(a,d)).forEach(function(a){for(b=0;b=0&&(j+=h(e[g].value)-i))}),j}},i.isWithinShape=function(a,b){var c,d=this,e=d.d3.select(a);return d.isTargetToShow(b.id)?"circle"===a.nodeName?c=d.isStepType(b)?d.isWithinStep(a,d.getYScale(b.id)(b.value)):d.isWithinCircle(a,1.5*d.pointSelectR(b)):"path"===a.nodeName&&(c=e.classed(l.bar)?d.isWithinBar(a):!0):c=!1,c},i.getInterpolate=function(a){var b=this,c=b.isInterpolationType(b.config.spline_interpolation_type)?b.config.spline_interpolation_type:"cardinal";return b.isSplineType(a)?c:b.isStepType(a)?b.config.line_step_type:"linear"},i.initLine=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.chartLines)},i.updateTargetsForLine=function(a){var b,c,d=this,e=d.config,f=d.classChartLine.bind(d),g=d.classLines.bind(d),h=d.classAreas.bind(d),i=d.classCircles.bind(d),j=d.classFocus.bind(d);b=d.main.select("."+l.chartLines).selectAll("."+l.chartLine).data(a).attr("class",function(a){return f(a)+j(a)}),c=b.enter().append("g").attr("class",f).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",g),c.append("g").attr("class",h),c.append("g").attr("class",function(a){return d.generateClass(l.selectedCircles,a.id)}),c.append("g").attr("class",i).style("cursor",function(a){return e.data_selection_isselectable(a)?"pointer":null}),a.forEach(function(a){d.main.selectAll("."+l.selectedCircles+d.getTargetSelectorSuffix(a.id)).selectAll("."+l.selectedCircle).each(function(b){b.value=a.values[b.index].value})})},i.updateLine=function(a){var b=this;b.mainLine=b.main.selectAll("."+l.lines).selectAll("."+l.line).data(b.lineData.bind(b)),b.mainLine.enter().append("path").attr("class",b.classLine.bind(b)).style("stroke",b.color),b.mainLine.style("opacity",b.initialOpacity.bind(b)).style("shape-rendering",function(a){return b.isStepType(a)?"crispEdges":""}).attr("transform",null),b.mainLine.exit().transition().duration(a).style("opacity",0).remove()},i.redrawLine=function(a,b){return[(b?this.mainLine.transition(Math.random().toString()):this.mainLine).attr("d",a).style("stroke",this.color).style("opacity",1)]},i.generateDrawLine=function(a,b){var c=this,d=c.config,e=c.d3.svg.line(),f=c.generateGetLinePoints(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x(i).y(h):e.x(h).y(i),d.line_connectNull||(e=e.defined(function(a){return null!=a.value})),function(a){var f,h=d.line_connectNull?c.filterRemoveNull(a.values):a.values,i=b?c.x:c.subX,j=g.call(c,a.id),k=0,l=0;return c.isLineType(a)?d.data_regions[a.id]?f=c.lineWithRegions(h,i,j,d.data_regions[a.id]):(c.isStepType(a)&&(h=c.convertValuesToStep(h)),f=e.interpolate(c.getInterpolate(a))(h)):(h[0]&&(k=i(h[0].x),l=j(h[0].value)),f=d.axis_rotated?"M "+l+" "+k:"M "+k+" "+l),f?f:"M 0 0"}},i.generateGetLinePoints=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isLineType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0l||a.value<0&&l>e)&&(l=e),[[k,l-(e-j)],[k,l-(e-j)],[k,l-(e-j)],[k,l-(e-j)]]}},i.lineWithRegions=function(a,b,c,d){function e(a,b){var c;for(c=0;c=h;h+=r)x+=i(a[g-1],a[g],h,o);w=a[g].x}return x},i.updateArea=function(a){var b=this,c=b.d3;b.mainArea=b.main.selectAll("."+l.areas).selectAll("."+l.area).data(b.lineData.bind(b)),b.mainArea.enter().append("path").attr("class",b.classArea.bind(b)).style("fill",b.color).style("opacity",function(){return b.orgAreaOpacity=+c.select(this).style("opacity"),0}),b.mainArea.style("opacity",b.orgAreaOpacity),b.mainArea.exit().transition().duration(a).style("opacity",0).remove()},i.redrawArea=function(a,b){return[(b?this.mainArea.transition(Math.random().toString()):this.mainArea).attr("d",a).style("fill",this.color).style("opacity",this.orgAreaOpacity)]},i.generateDrawArea=function(a,b){var c=this,d=c.config,e=c.d3.svg.area(),f=c.generateGetAreaPoints(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(c.getAreaBaseValue(a.id))},j=function(a,b){return d.data_groups.length>0?f(a,b)[1][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x0(i).x1(j).y(h):e.x(h).y0(d.area_above?0:i).y1(j),d.line_connectNull||(e=e.defined(function(a){return null!==a.value})),function(a){var b,f=d.line_connectNull?c.filterRemoveNull(a.values):a.values,g=0,h=0;return c.isAreaType(a)?(c.isStepType(a)&&(f=c.convertValuesToStep(f)),b=e.interpolate(c.getInterpolate(a))(f)):(f[0]&&(g=c.x(f[0].x),h=c.getYScale(a.id)(f[0].value)),b=d.axis_rotated?"M "+h+" "+g:"M "+g+" "+h),b?b:"M 0 0"}},i.getAreaBaseValue=function(){return 0},i.generateGetAreaPoints=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isAreaType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0l||a.value<0&&l>e)&&(l=e),[[k,j],[k,l-(e-j)],[k,l-(e-j)],[k,j]]}},i.updateCircle=function(){var a=this;a.mainCircle=a.main.selectAll("."+l.circles).selectAll("."+l.circle).data(a.lineOrScatterData.bind(a)),a.mainCircle.enter().append("circle").attr("class",a.classCircle.bind(a)).attr("r",a.pointR.bind(a)).style("fill",a.color),a.mainCircle.style("opacity",a.initialOpacityForCircle.bind(a)),a.mainCircle.exit().remove()},i.redrawCircle=function(a,b,c){var d=this.main.selectAll("."+l.selectedCircle);return[(c?this.mainCircle.transition(Math.random().toString()):this.mainCircle).style("opacity",this.opacityForCircle.bind(this)).style("fill",this.color).attr("cx",a).attr("cy",b),(c?d.transition(Math.random().toString()):d).attr("cx",a).attr("cy",b)]},i.circleX=function(a){return a.x||0===a.x?this.x(a.x):null},i.updateCircleY=function(){var a,b,c=this;c.config.data_groups.length>0?(a=c.getShapeIndices(c.isLineType),b=c.generateGetLinePoints(a),c.circleY=function(a,c){return b(a,c)[0][1]}):c.circleY=function(a){return c.getYScale(a.id)(a.value)}},i.getCircles=function(a,b){var c=this;return(b?c.main.selectAll("."+l.circles+c.getTargetSelectorSuffix(b)):c.main).selectAll("."+l.circle+(m(a)?"-"+a:""))},i.expandCircles=function(a,b,c){var d=this,e=d.pointExpandedR.bind(d);c&&d.unexpandCircles(),d.getCircles(a,b).classed(l.EXPANDED,!0).attr("r",e)},i.unexpandCircles=function(a){var b=this,c=b.pointR.bind(b);b.getCircles(a).filter(function(){return b.d3.select(this).classed(l.EXPANDED)}).classed(l.EXPANDED,!1).attr("r",c)},i.pointR=function(a){var b=this,c=b.config;return b.isStepType(a)?0:n(c.point_r)?c.point_r(a):c.point_r; -},i.pointExpandedR=function(a){var b=this,c=b.config;return c.point_focus_expand_enabled?c.point_focus_expand_r?c.point_focus_expand_r:1.75*b.pointR(a):b.pointR(a)},i.pointSelectR=function(a){var b=this,c=b.config;return n(c.point_select_r)?c.point_select_r(a):c.point_select_r?c.point_select_r:4*b.pointR(a)},i.isWithinCircle=function(a,b){var c=this.d3,d=c.mouse(a),e=c.select(a),f=+e.attr("cx"),g=+e.attr("cy");return Math.sqrt(Math.pow(f-d[0],2)+Math.pow(g-d[1],2))d.bar_width_max?d.bar_width_max:e},i.getBars=function(a,b){var c=this;return(b?c.main.selectAll("."+l.bars+c.getTargetSelectorSuffix(b)):c.main).selectAll("."+l.bar+(m(a)?"-"+a:""))},i.expandBars=function(a,b,c){var d=this;c&&d.unexpandBars(),d.getBars(a,b).classed(l.EXPANDED,!0)},i.unexpandBars=function(a){var b=this;b.getBars(a).classed(l.EXPANDED,!1)},i.generateDrawBar=function(a,b){var c=this,d=c.config,e=c.generateGetBarPoints(a,b);return function(a,b){var c=e(a,b),f=d.axis_rotated?1:0,g=d.axis_rotated?0:1,h="M "+c[0][f]+","+c[0][g]+" L"+c[1][f]+","+c[1][g]+" L"+c[2][f]+","+c[2][g]+" L"+c[3][f]+","+c[3][g]+" z";return h}},i.generateGetBarPoints=function(a,b){var c=this,d=b?c.subXAxis:c.xAxis,e=a.__max__+1,f=c.getBarW(d,e),g=c.getShapeX(f,e,a,!!b),h=c.getShapeY(!!b),i=c.getShapeOffset(c.isBarType,a,!!b),j=b?c.getSubYScale:c.getYScale;return function(a,b){var d=j.call(c,a.id)(0),e=i(a,b)||d,k=g(a),l=h(a);return c.config.axis_rotated&&(0l||a.value<0&&l>d)&&(l=d),[[k,e],[k,l-(d-e)],[k+f,l-(d-e)],[k+f,e]]}},i.isWithinBar=function(a){var b=this.d3.mouse(a),c=a.getBoundingClientRect(),d=a.pathSegList.getItem(0),e=a.pathSegList.getItem(1),f=Math.min(d.x,e.x),g=Math.min(d.y,e.y),h=c.width,i=c.height,j=2,k=f-j,l=f+h+j,m=g+i+j,n=g-j;return kf.width?d=f.width-g.width:0>d&&(d=4)),d},i.getYForText=function(a,b,c){var d,e=this,f=c.getBoundingClientRect();return e.config.axis_rotated?d=(a[0][0]+a[2][0]+.6*f.height)/2:(d=a[2][1],b.value<0||0===b.value&&!e.hasPositiveValue?(d+=f.height,e.isBarType(b)&&e.isSafari()?d-=3:!e.isBarType(b)&&e.isChrome()&&(d+=3)):d+=e.isBarType(b)?-3:-6),null!==b.value||e.config.axis_rotated||(dthis.height&&(d=this.height-4)),d},i.setTargetType=function(a,b){var c=this,d=c.config;c.mapToTargetIds(a).forEach(function(a){c.withoutFadeIn[a]=b===d.data_types[a],d.data_types[a]=b}),a||(d.data_type=b)},i.hasType=function(a,b){var c=this,d=c.config.data_types,e=!1;return b=b||c.data.targets,b&&b.length?b.forEach(function(b){var c=d[b.id];(c&&c.indexOf(a)>=0||!c&&"line"===a)&&(e=!0)}):Object.keys(d).length?Object.keys(d).forEach(function(b){d[b]===a&&(e=!0)}):e=c.config.data_type===a,e},i.hasArcType=function(a){return this.hasType("pie",a)||this.hasType("donut",a)||this.hasType("gauge",a)},i.isLineType=function(a){var b=this.config,c=o(a)?a:a.id;return!b.data_types[c]||["line","spline","area","area-spline","step","area-step"].indexOf(b.data_types[c])>=0},i.isStepType=function(a){var b=o(a)?a:a.id;return["step","area-step"].indexOf(this.config.data_types[b])>=0},i.isSplineType=function(a){var b=o(a)?a:a.id;return["spline","area-spline"].indexOf(this.config.data_types[b])>=0},i.isAreaType=function(a){var b=o(a)?a:a.id;return["area","area-spline","area-step"].indexOf(this.config.data_types[b])>=0},i.isBarType=function(a){var b=o(a)?a:a.id;return"bar"===this.config.data_types[b]},i.isScatterType=function(a){var b=o(a)?a:a.id;return"scatter"===this.config.data_types[b]},i.isPieType=function(a){var b=o(a)?a:a.id;return"pie"===this.config.data_types[b]},i.isGaugeType=function(a){var b=o(a)?a:a.id;return"gauge"===this.config.data_types[b]},i.isDonutType=function(a){var b=o(a)?a:a.id;return"donut"===this.config.data_types[b]},i.isArcType=function(a){return this.isPieType(a)||this.isDonutType(a)||this.isGaugeType(a)},i.lineData=function(a){return this.isLineType(a)?[a]:[]},i.arcData=function(a){return this.isArcType(a.data)?[a]:[]},i.barData=function(a){return this.isBarType(a)?a.values:[]},i.lineOrScatterData=function(a){return this.isLineType(a)||this.isScatterType(a)?a.values:[]},i.barOrLineData=function(a){return this.isBarType(a)||this.isLineType(a)?a.values:[]},i.isInterpolationType=function(a){return["linear","linear-closed","basis","basis-open","basis-closed","bundle","cardinal","cardinal-open","cardinal-closed","monotone"].indexOf(a)>=0},i.initGrid=function(){var a=this,b=a.config,c=a.d3;a.grid=a.main.append("g").attr("clip-path",a.clipPathForGrid).attr("class",l.grid),b.grid_x_show&&a.grid.append("g").attr("class",l.xgrids),b.grid_y_show&&a.grid.append("g").attr("class",l.ygrids),b.grid_focus_show&&a.grid.append("g").attr("class",l.xgridFocus).append("line").attr("class",l.xgridFocus),a.xgrid=c.selectAll([]),b.grid_lines_front||a.initGridLines()},i.initGridLines=function(){var a=this,b=a.d3;a.gridLines=a.main.append("g").attr("clip-path",a.clipPathForGrid).attr("class",l.grid+" "+l.gridLines),a.gridLines.append("g").attr("class",l.xgridLines),a.gridLines.append("g").attr("class",l.ygridLines),a.xgridLines=b.selectAll([])},i.updateXGrid=function(a){var b=this,c=b.config,d=b.d3,e=b.generateGridData(c.grid_x_type,b.x),f=b.isCategorized()?b.xAxis.tickOffset():0;b.xgridAttr=c.axis_rotated?{x1:0,x2:b.width,y1:function(a){return b.x(a)-f},y2:function(a){return b.x(a)-f}}:{x1:function(a){return b.x(a)+f},x2:function(a){return b.x(a)+f},y1:0,y2:b.height},b.xgrid=b.main.select("."+l.xgrids).selectAll("."+l.xgrid).data(e),b.xgrid.enter().append("line").attr("class",l.xgrid),a||b.xgrid.attr(b.xgridAttr).style("opacity",function(){return+d.select(this).attr(c.axis_rotated?"y1":"x1")===(c.axis_rotated?b.height:0)?0:1}),b.xgrid.exit().remove()},i.updateYGrid=function(){var a=this,b=a.config,c=a.yAxis.tickValues()||a.y.ticks(b.grid_y_ticks);a.ygrid=a.main.select("."+l.ygrids).selectAll("."+l.ygrid).data(c),a.ygrid.enter().append("line").attr("class",l.ygrid),a.ygrid.attr("x1",b.axis_rotated?a.y:0).attr("x2",b.axis_rotated?a.y:a.width).attr("y1",b.axis_rotated?0:a.y).attr("y2",b.axis_rotated?a.height:a.y),a.ygrid.exit().remove(),a.smoothLines(a.ygrid,"grid")},i.gridTextAnchor=function(a){return a.position?a.position:"end"},i.gridTextDx=function(a){return"start"===a.position?4:"middle"===a.position?0:-4},i.xGridTextX=function(a){return"start"===a.position?-this.height:"middle"===a.position?-this.height/2:0},i.yGridTextX=function(a){return"start"===a.position?0:"middle"===a.position?this.width/2:this.width},i.updateGrid=function(a){var b,c,d,e=this,f=e.main,g=e.config;e.grid.style("visibility",e.hasArcType()?"hidden":"visible"),f.select("line."+l.xgridFocus).style("visibility","hidden"),g.grid_x_show&&e.updateXGrid(),e.xgridLines=f.select("."+l.xgridLines).selectAll("."+l.xgridLine).data(g.grid_x_lines),b=e.xgridLines.enter().append("g").attr("class",function(a){return l.xgridLine+(a["class"]?" "+a["class"]:"")}),b.append("line").style("opacity",0),b.append("text").attr("text-anchor",e.gridTextAnchor).attr("transform",g.axis_rotated?"":"rotate(-90)").attr("dx",e.gridTextDx).attr("dy",-5).style("opacity",0),e.xgridLines.exit().transition().duration(a).style("opacity",0).remove(),g.grid_y_show&&e.updateYGrid(),e.ygridLines=f.select("."+l.ygridLines).selectAll("."+l.ygridLine).data(g.grid_y_lines),c=e.ygridLines.enter().append("g").attr("class",function(a){return l.ygridLine+(a["class"]?" "+a["class"]:"")}),c.append("line").style("opacity",0),c.append("text").attr("text-anchor",e.gridTextAnchor).attr("transform",g.axis_rotated?"rotate(-90)":"").attr("dx",e.gridTextDx).attr("dy",-5).style("opacity",0),d=e.yv.bind(e),e.ygridLines.select("line").transition().duration(a).attr("x1",g.axis_rotated?d:0).attr("x2",g.axis_rotated?d:e.width).attr("y1",g.axis_rotated?0:d).attr("y2",g.axis_rotated?e.height:d).style("opacity",1),e.ygridLines.select("text").transition().duration(a).attr("x",g.axis_rotated?e.xGridTextX.bind(e):e.yGridTextX.bind(e)).attr("y",d).text(function(a){return a.text}).style("opacity",1),e.ygridLines.exit().transition().duration(a).style("opacity",0).remove()},i.redrawGrid=function(a){var b=this,c=b.config,d=b.xv.bind(b),e=b.xgridLines.select("line"),f=b.xgridLines.select("text");return[(a?e.transition():e).attr("x1",c.axis_rotated?0:d).attr("x2",c.axis_rotated?b.width:d).attr("y1",c.axis_rotated?d:0).attr("y2",c.axis_rotated?d:b.height).style("opacity",1),(a?f.transition():f).attr("x",c.axis_rotated?b.yGridTextX.bind(b):b.xGridTextX.bind(b)).attr("y",d).text(function(a){return a.text}).style("opacity",1)]},i.showXGridFocus=function(a){var b=this,c=b.config,d=a.filter(function(a){return a&&m(a.value)}),e=b.main.selectAll("line."+l.xgridFocus),f=b.xx.bind(b);c.tooltip_show&&(b.hasType("scatter")||b.hasArcType()||(e.style("visibility","visible").data([d[0]]).attr(c.axis_rotated?"y1":"x1",f).attr(c.axis_rotated?"y2":"x2",f),b.smoothLines(e,"grid")))},i.hideXGridFocus=function(){this.main.select("line."+l.xgridFocus).style("visibility","hidden")},i.updateXgridFocus=function(){var a=this,b=a.config;a.main.select("line."+l.xgridFocus).attr("x1",b.axis_rotated?0:-10).attr("x2",b.axis_rotated?a.width:-10).attr("y1",b.axis_rotated?-10:0).attr("y2",b.axis_rotated?-10:a.height)},i.generateGridData=function(a,b){var c,d,e,f,g=this,h=[],i=g.main.select("."+l.axisX).selectAll(".tick").size();if("year"===a)for(c=g.getXDomain(),d=c[0].getFullYear(),e=c[1].getFullYear(),f=d;e>=f;f++)h.push(new Date(f+"-01-01 00:00:00"));else h=b.ticks(10),h.length>i&&(h=h.filter(function(a){return(""+a).indexOf(".")<0}));return h},i.getGridFilterToRemove=function(a){return a?function(b){var c=!1;return[].concat(a).forEach(function(a){("value"in a&&b.value===a.value||"class"in a&&b["class"]===a["class"])&&(c=!0)}),c}:function(){return!0}},i.removeGridLines=function(a,b){var c=this,d=c.config,e=c.getGridFilterToRemove(a),f=function(a){return!e(a)},g=b?l.xgridLines:l.ygridLines,h=b?l.xgridLine:l.ygridLine;c.main.select("."+g).selectAll("."+h).filter(e).transition().duration(d.transition_duration).style("opacity",0).remove(),b?d.grid_x_lines=d.grid_x_lines.filter(f):d.grid_y_lines=d.grid_y_lines.filter(f)},i.initTooltip=function(){var a,b=this,c=b.config;if(b.tooltip=b.selectChart.style("position","relative").append("div").attr("class",l.tooltipContainer).style("position","absolute").style("pointer-events","none").style("display","none"),c.tooltip_init_show){if(b.isTimeSeries()&&o(c.tooltip_init_x)){for(c.tooltip_init_x=b.parseDate(c.tooltip_init_x),a=0;a0&&d>0&&(c=a?q.indexOf(a.id):null,d=b?q.indexOf(b.id):null),p?c-d:d-c})}for(f=0;f"+(g||0===g?""+g+"":"")),h=y(o(a[f].value,a[f].ratio,a[f].id,a[f].index,a)),void 0!==h)){if(null===a[f].name)continue;i=y(n(a[f].name,a[f].ratio,a[f].id,a[f].index)),j=k.levelColor?k.levelColor(a[f].value):d(a[f].id),e+="",e+=""+i+"",e+=""+h+"",e+=""}return e+""},i.tooltipPosition=function(a,b,c,d){var e,f,g,h,i,j=this,k=j.config,l=j.d3,m=j.hasArcType(),n=l.mouse(d);return m?(f=(j.width-(j.isLegendRight?j.getLegendWidth():0))/2+n[0],h=j.height/2+n[1]+20):(e=j.getSvgLeft(!0),k.axis_rotated?(f=e+n[0]+100,g=f+b,i=j.currentWidth-j.getCurrentPaddingRight(),h=j.x(a[0].x)+20):(f=e+j.getCurrentPaddingLeft(!0)+j.x(a[0].x)+20,g=f+b,i=e+j.currentWidth-j.getCurrentPaddingRight(),h=n[1]+15),g>i&&(f-=g-i+20),h+c>j.currentHeight&&(h-=c+30)),0>h&&(h=0),{top:h,left:f}},i.showTooltip=function(a,b){var c,d,e,f=this,g=f.config,h=f.hasArcType(),j=a.filter(function(a){return a&&m(a.value)}),k=g.tooltip_position||i.tooltipPosition;0!==j.length&&g.tooltip_show&&(f.tooltip.html(g.tooltip_contents.call(f,a,f.axis.getXAxisTickFormat(),f.getYFormat(h),f.color)).style("display","block"),c=f.tooltip.property("offsetWidth"),d=f.tooltip.property("offsetHeight"),e=k.call(this,j,c,d,b),f.tooltip.style("top",e.top+"px").style("left",e.left+"px"))},i.hideTooltip=function(){this.tooltip.style("display","none")},i.initLegend=function(){var a=this;return a.legendItemTextBox={},a.legendHasRendered=!1,a.legend=a.svg.append("g").attr("transform",a.getTranslate("legend")),a.config.legend_show?void a.updateLegendWithDefaults():(a.legend.style("visibility","hidden"),void(a.hiddenLegendIds=a.mapToIds(a.data.targets)))},i.updateLegendWithDefaults=function(){var a=this;a.updateLegend(a.mapToIds(a.data.targets),{withTransform:!1,withTransitionForTransform:!1,withTransition:!1})},i.updateSizeForLegend=function(a,b){var c=this,d=c.config,e={top:c.isLegendTop?c.getCurrentPaddingTop()+d.legend_inset_y+5.5:c.currentHeight-a-c.getCurrentPaddingBottom()-d.legend_inset_y,left:c.isLegendLeft?c.getCurrentPaddingLeft()+d.legend_inset_x+.5:c.currentWidth-b-c.getCurrentPaddingRight()-d.legend_inset_x+.5};c.margin3={top:c.isLegendRight?0:c.isLegendInset?e.top:c.currentHeight-a,right:NaN,bottom:0,left:c.isLegendRight?c.currentWidth-b:c.isLegendInset?e.left:0}},i.transformLegend=function(a){var b=this;(a?b.legend.transition():b.legend).attr("transform",b.getTranslate("legend"))},i.updateLegendStep=function(a){this.legendStep=a},i.updateLegendItemWidth=function(a){this.legendItemWidth=a},i.updateLegendItemHeight=function(a){this.legendItemHeight=a},i.getLegendWidth=function(){var a=this;return a.config.legend_show?a.isLegendRight||a.isLegendInset?a.legendItemWidth*(a.legendStep+1):a.currentWidth:0},i.getLegendHeight=function(){var a=this,b=0;return a.config.legend_show&&(b=a.isLegendRight?a.currentHeight:Math.max(20,a.legendItemHeight)*(a.legendStep+1)),b},i.opacityForLegend=function(a){return a.classed(l.legendItemHidden)?null:1},i.opacityForUnfocusedLegend=function(a){return a.classed(l.legendItemHidden)?null:.3},i.toggleFocusLegend=function(a,b){var c=this;a=c.mapToTargetIds(a),c.legend.selectAll("."+l.legendItem).filter(function(b){return a.indexOf(b)>=0}).classed(l.legendItemFocused,b).transition().duration(100).style("opacity",function(){var a=b?c.opacityForLegend:c.opacityForUnfocusedLegend;return a.call(c,c.d3.select(this))})},i.revertLegend=function(){var a=this,b=a.d3;a.legend.selectAll("."+l.legendItem).classed(l.legendItemFocused,!1).transition().duration(100).style("opacity",function(){return a.opacityForLegend(b.select(this))})},i.showLegend=function(a){var b=this,c=b.config;c.legend_show||(c.legend_show=!0,b.legend.style("visibility","visible"),b.legendHasRendered||b.updateLegendWithDefaults()),b.removeHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("visibility","visible").transition().style("opacity",function(){return b.opacityForLegend(b.d3.select(this))})},i.hideLegend=function(a){var b=this,c=b.config;c.legend_show&&u(a)&&(c.legend_show=!1,b.legend.style("visibility","hidden")),b.addHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("opacity",0).style("visibility","hidden")},i.clearLegendItemTextBoxCache=function(){this.legendItemTextBox={}},i.updateLegend=function(a,b,c){function d(a,b){return y.legendItemTextBox[b]||(y.legendItemTextBox[b]=y.getTextRect(a.textContent,l.legendItem,a)),y.legendItemTextBox[b]}function e(b,c,e){function f(a,b){b||(g=(o-G-n)/2,E>g&&(g=(o-n)/2,G=0,M++)),L[a]=M,K[M]=y.isLegendInset?10:g,H[a]=G,G+=n}var g,h,i=0===e,j=e===a.length-1,k=d(b,c),l=k.width+F+(!j||y.isLegendRight||y.isLegendInset?B:0)+z.legend_padding,m=k.height+A,n=y.isLegendRight||y.isLegendInset?m:l,o=y.isLegendRight||y.isLegendInset?y.getLegendHeight():y.getLegendWidth();return i&&(G=0,M=0,C=0,D=0),z.legend_show&&!y.isLegendToShow(c)?void(I[c]=J[c]=L[c]=H[c]=0):(I[c]=l,J[c]=m,(!C||l>=C)&&(C=l),(!D||m>=D)&&(D=m),h=y.isLegendRight||y.isLegendInset?D:C,void(z.legend_equally?(Object.keys(I).forEach(function(a){I[a]=C}),Object.keys(J).forEach(function(a){J[a]=D}),g=(o-h*a.length)/2,E>g?(G=0,M=0,a.forEach(function(a){f(a)})):f(c,!0)):f(c)))}var f,g,h,i,j,k,m,n,o,p,r,s,t,u,v,x,y=this,z=y.config,A=4,B=10,C=0,D=0,E=10,F=z.legend_item_tile_width+5,G=0,H={},I={},J={},K=[0],L={},M=0;a=a.filter(function(a){return!q(z.data_names[a])||null!==z.data_names[a]}),b=b||{},r=w(b,"withTransition",!0),s=w(b,"withTransitionForTransform",!0),y.isLegendInset&&(M=z.legend_inset_step?z.legend_inset_step:a.length,y.updateLegendStep(M)),y.isLegendRight?(f=function(a){return C*L[a]},i=function(a){return K[L[a]]+H[a]}):y.isLegendInset?(f=function(a){return C*L[a]+10},i=function(a){return K[L[a]]+H[a]}):(f=function(a){return K[L[a]]+H[a]},i=function(a){return D*L[a]}),g=function(a,b){return f(a,b)+4+z.legend_item_tile_width},j=function(a,b){return i(a,b)+9},h=function(a,b){return f(a,b)},k=function(a,b){return i(a,b)-5},m=function(a,b){return f(a,b)-2},n=function(a,b){return f(a,b)-2+z.legend_item_tile_width},o=function(a,b){return i(a,b)+4},p=y.legend.selectAll("."+l.legendItem).data(a).enter().append("g").attr("class",function(a){return y.generateClass(l.legendItem,a)}).style("visibility",function(a){return y.isLegendToShow(a)?"visible":"hidden"}).style("cursor","pointer").on("click",function(a){z.legend_item_onclick?z.legend_item_onclick.call(y,a):y.d3.event.altKey?(y.api.hide(),y.api.show(a)):(y.api.toggle(a),y.isTargetToShow(a)?y.api.focus(a):y.api.revert())}).on("mouseover",function(a){z.legend_item_onmouseover?z.legend_item_onmouseover.call(y,a):(y.d3.select(this).classed(l.legendItemFocused,!0),!y.transiting&&y.isTargetToShow(a)&&y.api.focus(a))}).on("mouseout",function(a){z.legend_item_onmouseout?z.legend_item_onmouseout.call(y,a):(y.d3.select(this).classed(l.legendItemFocused,!1),y.api.revert())}),p.append("text").text(function(a){return q(z.data_names[a])?z.data_names[a]:a}).each(function(a,b){e(this,a,b)}).style("pointer-events","none").attr("x",y.isLegendRight||y.isLegendInset?g:-200).attr("y",y.isLegendRight||y.isLegendInset?-200:j),p.append("rect").attr("class",l.legendItemEvent).style("fill-opacity",0).attr("x",y.isLegendRight||y.isLegendInset?h:-200).attr("y",y.isLegendRight||y.isLegendInset?-200:k),p.append("line").attr("class",l.legendItemTile).style("stroke",y.color).style("pointer-events","none").attr("x1",y.isLegendRight||y.isLegendInset?m:-200).attr("y1",y.isLegendRight||y.isLegendInset?-200:o).attr("x2",y.isLegendRight||y.isLegendInset?n:-200).attr("y2",y.isLegendRight||y.isLegendInset?-200:o).attr("stroke-width",z.legend_item_tile_height),x=y.legend.select("."+l.legendBackground+" rect"),y.isLegendInset&&C>0&&0===x.size()&&(x=y.legend.insert("g","."+l.legendItem).attr("class",l.legendBackground).append("rect")),t=y.legend.selectAll("text").data(a).text(function(a){return q(z.data_names[a])?z.data_names[a]:a}).each(function(a,b){e(this,a,b)}),(r?t.transition():t).attr("x",g).attr("y",j),u=y.legend.selectAll("rect."+l.legendItemEvent).data(a),(r?u.transition():u).attr("width",function(a){return I[a]}).attr("height",function(a){return J[a]}).attr("x",h).attr("y",k),v=y.legend.selectAll("line."+l.legendItemTile).data(a),(r?v.transition():v).style("stroke",y.color).attr("x1",m).attr("y1",o).attr("x2",n).attr("y2",o),x&&(r?x.transition():x).attr("height",y.getLegendHeight()-12).attr("width",C*(M+1)+10),y.legend.selectAll("."+l.legendItem).classed(l.legendItemHidden,function(a){return!y.isTargetToShow(a)}),y.updateLegendItemWidth(C),y.updateLegendItemHeight(D),y.updateLegendStep(M),y.updateSizes(),y.updateScales(),y.updateSvgSize(),y.transformAll(s,c),y.legendHasRendered=!0},i.initTitle=function(){var a=this;a.title=a.svg.append("text").text(a.config.title_text).attr("class",a.CLASS.title)},i.redrawTitle=function(){var a=this;a.title.attr("x",a.xForTitle.bind(a)).attr("y",a.yForTitle.bind(a))},i.xForTitle=function(){var a,b=this,c=b.config,d=c.title_position||"left";return a=d.indexOf("right")>=0?b.currentWidth-b.getTextRect(b.title.node().textContent,b.CLASS.title,b.title.node()).width-c.title_padding.right:d.indexOf("center")>=0?(b.currentWidth-b.getTextRect(b.title.node().textContent,b.CLASS.title,b.title.node()).width)/2:c.title_padding.left},i.yForTitle=function(){var a=this;return a.config.title_padding.top+a.getTextRect(a.title.node().textContent,a.CLASS.title,a.title.node()).height},i.getTitlePadding=function(){var a=this;return a.yForTitle()+a.config.title_padding.bottom},c(b,f),f.prototype.init=function(){var a=this.owner,b=a.config,c=a.main;a.axes.x=c.append("g").attr("class",l.axis+" "+l.axisX).attr("clip-path",a.clipPathForXAxis).attr("transform",a.getTranslate("x")).style("visibility",b.axis_x_show?"visible":"hidden"),a.axes.x.append("text").attr("class",l.axisXLabel).attr("transform",b.axis_rotated?"rotate(-90)":"").style("text-anchor",this.textAnchorForXAxisLabel.bind(this)),a.axes.y=c.append("g").attr("class",l.axis+" "+l.axisY).attr("clip-path",b.axis_y_inner?"":a.clipPathForYAxis).attr("transform",a.getTranslate("y")).style("visibility",b.axis_y_show?"visible":"hidden"),a.axes.y.append("text").attr("class",l.axisYLabel).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",this.textAnchorForYAxisLabel.bind(this)),a.axes.y2=c.append("g").attr("class",l.axis+" "+l.axisY2).attr("transform",a.getTranslate("y2")).style("visibility",b.axis_y2_show?"visible":"hidden"),a.axes.y2.append("text").attr("class",l.axisY2Label).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",this.textAnchorForY2AxisLabel.bind(this))},f.prototype.getXAxis=function(a,b,c,d,e,f,h){var i=this.owner,j=i.config,k={isCategory:i.isCategorized(),withOuterTick:e,tickMultiline:j.axis_x_tick_multiline,tickWidth:j.axis_x_tick_width,tickTextRotate:h?0:j.axis_x_tick_rotate,withoutTransition:f},l=g(i.d3,k).scale(a).orient(b);return i.isTimeSeries()&&d&&"function"!=typeof d&&(d=d.map(function(a){return i.parseDate(a)})),l.tickFormat(c).tickValues(d),i.isCategorized()&&(l.tickCentered(j.axis_x_tick_centered),u(j.axis_x_tick_culling)&&(j.axis_x_tick_culling=!1)),l},f.prototype.updateXAxisTickValues=function(a,b){var c,d=this.owner,e=d.config;return(e.axis_x_tick_fit||e.axis_x_tick_count)&&(c=this.generateTickValues(d.mapTargetsToUniqueXs(a),e.axis_x_tick_count,d.isTimeSeries())),b?b.tickValues(c):(d.xAxis.tickValues(c),d.subXAxis.tickValues(c)),c},f.prototype.getYAxis=function(a,b,c,d,e,f,h){var i=this.owner,j=i.config,k={withOuterTick:e,withoutTransition:f,tickTextRotate:h?0:j.axis_y_tick_rotate},l=g(i.d3,k).scale(a).orient(b).tickFormat(c);return i.isTimeSeriesY()?l.ticks(i.d3.time[j.axis_y_tick_time_value],j.axis_y_tick_time_interval):l.tickValues(d),l},f.prototype.getId=function(a){var b=this.owner.config;return a in b.data_axes?b.data_axes[a]:"y"},f.prototype.getXAxisTickFormat=function(){var a=this.owner,b=a.config,c=a.isTimeSeries()?a.defaultAxisTimeFormat:a.isCategorized()?a.categoryName:function(a){return 0>a?a.toFixed(0):a};return b.axis_x_tick_format&&(n(b.axis_x_tick_format)?c=b.axis_x_tick_format:a.isTimeSeries()&&(c=function(c){return c?a.axisTimeFormat(b.axis_x_tick_format)(c):""})),n(c)?function(b){return c.call(a,b)}:c},f.prototype.getTickValues=function(a,b){return a?a:b?b.tickValues():void 0},f.prototype.getXAxisTickValues=function(){return this.getTickValues(this.owner.config.axis_x_tick_values,this.owner.xAxis)},f.prototype.getYAxisTickValues=function(){return this.getTickValues(this.owner.config.axis_y_tick_values,this.owner.yAxis)},f.prototype.getY2AxisTickValues=function(){return this.getTickValues(this.owner.config.axis_y2_tick_values,this.owner.y2Axis)},f.prototype.getLabelOptionByAxisId=function(a){var b,c=this.owner,d=c.config;return"y"===a?b=d.axis_y_label:"y2"===a?b=d.axis_y2_label:"x"===a&&(b=d.axis_x_label),b},f.prototype.getLabelText=function(a){var b=this.getLabelOptionByAxisId(a);return o(b)?b:b?b.text:null},f.prototype.setLabelText=function(a,b){var c=this.owner,d=c.config,e=this.getLabelOptionByAxisId(a);o(e)?"y"===a?d.axis_y_label=b:"y2"===a?d.axis_y2_label=b:"x"===a&&(d.axis_x_label=b):e&&(e.text=b)},f.prototype.getLabelPosition=function(a,b){var c=this.getLabelOptionByAxisId(a),d=c&&"object"==typeof c&&c.position?c.position:b;return{isInner:d.indexOf("inner")>=0,isOuter:d.indexOf("outer")>=0,isLeft:d.indexOf("left")>=0,isCenter:d.indexOf("center")>=0,isRight:d.indexOf("right")>=0,isTop:d.indexOf("top")>=0,isMiddle:d.indexOf("middle")>=0,isBottom:d.indexOf("bottom")>=0}},f.prototype.getXAxisLabelPosition=function(){return this.getLabelPosition("x",this.owner.config.axis_rotated?"inner-top":"inner-right")},f.prototype.getYAxisLabelPosition=function(){return this.getLabelPosition("y",this.owner.config.axis_rotated?"inner-right":"inner-top")},f.prototype.getY2AxisLabelPosition=function(){return this.getLabelPosition("y2",this.owner.config.axis_rotated?"inner-right":"inner-top")},f.prototype.getLabelPositionById=function(a){return"y2"===a?this.getY2AxisLabelPosition():"y"===a?this.getYAxisLabelPosition():this.getXAxisLabelPosition()},f.prototype.textForXAxisLabel=function(){return this.getLabelText("x")},f.prototype.textForYAxisLabel=function(){return this.getLabelText("y")},f.prototype.textForY2AxisLabel=function(){return this.getLabelText("y2")},f.prototype.xForAxisLabel=function(a,b){var c=this.owner;return a?b.isLeft?0:b.isCenter?c.width/2:c.width:b.isBottom?-c.height:b.isMiddle?-c.height/2:0},f.prototype.dxForAxisLabel=function(a,b){return a?b.isLeft?"0.5em":b.isRight?"-0.5em":"0":b.isTop?"-0.5em":b.isBottom?"0.5em":"0"},f.prototype.textAnchorForAxisLabel=function(a,b){return a?b.isLeft?"start":b.isCenter?"middle":"end":b.isBottom?"start":b.isMiddle?"middle":"end"},f.prototype.xForXAxisLabel=function(){return this.xForAxisLabel(!this.owner.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.xForYAxisLabel=function(){return this.xForAxisLabel(this.owner.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.xForY2AxisLabel=function(){return this.xForAxisLabel(this.owner.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.dxForXAxisLabel=function(){return this.dxForAxisLabel(!this.owner.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.dxForYAxisLabel=function(){return this.dxForAxisLabel(this.owner.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.dxForY2AxisLabel=function(){return this.dxForAxisLabel(this.owner.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.dyForXAxisLabel=function(){var a=this.owner,b=a.config,c=this.getXAxisLabelPosition();return b.axis_rotated?c.isInner?"1.2em":-25-this.getMaxTickWidth("x"):c.isInner?"-0.5em":b.axis_x_height?b.axis_x_height-10:"3em"},f.prototype.dyForYAxisLabel=function(){var a=this.owner,b=this.getYAxisLabelPosition();return a.config.axis_rotated?b.isInner?"-0.5em":"3em":b.isInner?"1.2em":-10-(a.config.axis_y_inner?0:this.getMaxTickWidth("y")+10)},f.prototype.dyForY2AxisLabel=function(){var a=this.owner,b=this.getY2AxisLabelPosition();return a.config.axis_rotated?b.isInner?"1.2em":"-2.2em":b.isInner?"-0.5em":15+(a.config.axis_y2_inner?0:this.getMaxTickWidth("y2")+15)},f.prototype.textAnchorForXAxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(!a.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.textAnchorForYAxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(a.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.textAnchorForY2AxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(a.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.getMaxTickWidth=function(a,b){var c,d,e,f,g,h=this.owner,i=h.config,j=0;return b&&h.currentMaxTickWidths[a]?h.currentMaxTickWidths[a]:(h.svg&&(c=h.filterTargetsToShow(h.data.targets),"y"===a?(d=h.y.copy().domain(h.getYDomain(c,"y")),e=this.getYAxis(d,h.yOrient,i.axis_y_tick_format,h.yAxisTickValues,!1,!0,!0)):"y2"===a?(d=h.y2.copy().domain(h.getYDomain(c,"y2")), -e=this.getYAxis(d,h.y2Orient,i.axis_y2_tick_format,h.y2AxisTickValues,!1,!0,!0)):(d=h.x.copy().domain(h.getXDomain(c)),e=this.getXAxis(d,h.xOrient,h.xAxisTickFormat,h.xAxisTickValues,!1,!0,!0),this.updateXAxisTickValues(c,e)),f=h.d3.select("body").append("div").classed("c3",!0),g=f.append("svg").style("visibility","hidden").style("position","fixed").style("top",0).style("left",0),g.append("g").call(e).each(function(){h.d3.select(this).selectAll("text").each(function(){var a=this.getBoundingClientRect();j=j?h.currentMaxTickWidths[a]:j,h.currentMaxTickWidths[a])},f.prototype.updateLabels=function(a){var b=this.owner,c=b.main.select("."+l.axisX+" ."+l.axisXLabel),d=b.main.select("."+l.axisY+" ."+l.axisYLabel),e=b.main.select("."+l.axisY2+" ."+l.axisY2Label);(a?c.transition():c).attr("x",this.xForXAxisLabel.bind(this)).attr("dx",this.dxForXAxisLabel.bind(this)).attr("dy",this.dyForXAxisLabel.bind(this)).text(this.textForXAxisLabel.bind(this)),(a?d.transition():d).attr("x",this.xForYAxisLabel.bind(this)).attr("dx",this.dxForYAxisLabel.bind(this)).attr("dy",this.dyForYAxisLabel.bind(this)).text(this.textForYAxisLabel.bind(this)),(a?e.transition():e).attr("x",this.xForY2AxisLabel.bind(this)).attr("dx",this.dxForY2AxisLabel.bind(this)).attr("dy",this.dyForY2AxisLabel.bind(this)).text(this.textForY2AxisLabel.bind(this))},f.prototype.getPadding=function(a,b,c,d){var e="number"==typeof a?a:a[b];return m(e)?"ratio"===a.unit?a[b]*d:this.convertPixelsToAxisPadding(e,d):c},f.prototype.convertPixelsToAxisPadding=function(a,b){var c=this.owner,d=c.config.axis_rotated?c.width:c.height;return b*(a/d)},f.prototype.generateTickValues=function(a,b,c){var d,e,f,g,h,i,j,k=a;if(b)if(d=n(b)?b():b,1===d)k=[a[0]];else if(2===d)k=[a[0],a[a.length-1]];else if(d>2){for(g=d-2,e=a[0],f=a[a.length-1],h=(f-e)/(g+1),k=[e],i=0;g>i;i++)j=+e+h*(i+1),k.push(c?new Date(j):j);k.push(f)}return c||(k=k.sort(function(a,b){return a-b})),k},f.prototype.generateTransitions=function(a){var b=this.owner,c=b.axes;return{axisX:a?c.x.transition().duration(a):c.x,axisY:a?c.y.transition().duration(a):c.y,axisY2:a?c.y2.transition().duration(a):c.y2,axisSubX:a?c.subx.transition().duration(a):c.subx}},f.prototype.redraw=function(a,b){var c=this.owner;c.axes.x.style("opacity",b?0:1),c.axes.y.style("opacity",b?0:1),c.axes.y2.style("opacity",b?0:1),c.axes.subx.style("opacity",b?0:1),a.axisX.call(c.xAxis),a.axisY.call(c.yAxis),a.axisY2.call(c.y2Axis),a.axisSubX.call(c.subXAxis)},i.getClipPath=function(b){var c=a.navigator.appVersion.toLowerCase().indexOf("msie 9.")>=0;return"url("+(c?"":document.URL.split("#")[0])+"#"+b+")"},i.appendClip=function(a,b){return a.append("clipPath").attr("id",b).append("rect")},i.getAxisClipX=function(a){var b=Math.max(30,this.margin.left);return a?-(1+b):-(b-1)},i.getAxisClipY=function(a){return a?-20:-this.margin.top},i.getXAxisClipX=function(){var a=this;return a.getAxisClipX(!a.config.axis_rotated)},i.getXAxisClipY=function(){var a=this;return a.getAxisClipY(!a.config.axis_rotated)},i.getYAxisClipX=function(){var a=this;return a.config.axis_y_inner?-1:a.getAxisClipX(a.config.axis_rotated)},i.getYAxisClipY=function(){var a=this;return a.getAxisClipY(a.config.axis_rotated)},i.getAxisClipWidth=function(a){var b=this,c=Math.max(30,b.margin.left),d=Math.max(30,b.margin.right);return a?b.width+2+c+d:b.margin.left+20},i.getAxisClipHeight=function(a){return(a?this.margin.bottom:this.margin.top+this.height)+20},i.getXAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(!a.config.axis_rotated)},i.getXAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(!a.config.axis_rotated)},i.getYAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(a.config.axis_rotated)+(a.config.axis_y_inner?20:0)},i.getYAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(a.config.axis_rotated)},i.initPie=function(){var a=this,b=a.d3,c=a.config;a.pie=b.layout.pie().value(function(a){return a.values.reduce(function(a,b){return a+b.value},0)}),c.data_order||a.pie.sort(null)},i.updateRadius=function(){var a=this,b=a.config,c=b.gauge_width||b.donut_width;a.radiusExpanded=Math.min(a.arcWidth,a.arcHeight)/2,a.radius=.95*a.radiusExpanded,a.innerRadiusRatio=c?(a.radius-c)/a.radius:.6,a.innerRadius=a.hasType("donut")||a.hasType("gauge")?a.radius*a.innerRadiusRatio:0},i.updateArc=function(){var a=this;a.svgArc=a.getSvgArc(),a.svgArcExpanded=a.getSvgArcExpanded(),a.svgArcExpandedSub=a.getSvgArcExpanded(.98)},i.updateAngle=function(a){var b,c,d,e,f=this,g=f.config,h=!1,i=0;return g?(f.pie(f.filterTargetsToShow(f.data.targets)).forEach(function(b){h||b.data.id!==a.data.id||(h=!0,a=b,a.index=i),i++}),isNaN(a.startAngle)&&(a.startAngle=0),isNaN(a.endAngle)&&(a.endAngle=a.startAngle),f.isGaugeType(a.data)&&(b=g.gauge_min,c=g.gauge_max,d=Math.PI*(g.gauge_fullCircle?2:1)/(c-b),e=a.value.375?1.175-36/g.radius:.8)*g.radius/e:0,j="translate("+c*f+","+d*f+")"),j},i.getArcRatio=function(a){var b=this,c=b.config,d=Math.PI*(b.hasType("gauge")&&!c.gauge_fullCircle?1:2);return a?(a.endAngle-a.startAngle)/d:null},i.convertToArcData=function(a){return this.addName({id:a.data.id,value:a.value,ratio:this.getArcRatio(a),index:a.index})},i.textForArcLabel=function(a){var b,c,d,e,f,g=this;return g.shouldShowArcLabel()?(b=g.updateAngle(a),c=b?b.value:null,d=g.getArcRatio(b),e=a.data.id,g.hasType("gauge")||g.meetsArcLabelThreshold(d)?(f=g.getArcLabelFormat(),f?f(c,d,e):g.defaultArcValueFormat(c,d)):""):""},i.expandArc=function(b){var c,d=this;return d.transiting?void(c=a.setInterval(function(){d.transiting||(a.clearInterval(c),d.legend.selectAll(".c3-legend-item-focused").size()>0&&d.expandArc(b))},10)):(b=d.mapToTargetIds(b),void d.svg.selectAll(d.selectorTargets(b,"."+l.chartArc)).each(function(a){d.shouldExpand(a.data.id)&&d.d3.select(this).selectAll("path").transition().duration(d.expandDuration(a.data.id)).attr("d",d.svgArcExpanded).transition().duration(2*d.expandDuration(a.data.id)).attr("d",d.svgArcExpandedSub).each(function(a){d.isDonutType(a.data)})}))},i.unexpandArc=function(a){var b=this;b.transiting||(a=b.mapToTargetIds(a),b.svg.selectAll(b.selectorTargets(a,"."+l.chartArc)).selectAll("path").transition().duration(function(a){return b.expandDuration(a.data.id)}).attr("d",b.svgArc),b.svg.selectAll("."+l.arc).style("opacity",1))},i.expandDuration=function(a){var b=this,c=b.config;return b.isDonutType(a)?c.donut_expand_duration:b.isGaugeType(a)?c.gauge_expand_duration:b.isPieType(a)?c.pie_expand_duration:50},i.shouldExpand=function(a){var b=this,c=b.config;return b.isDonutType(a)&&c.donut_expand||b.isGaugeType(a)&&c.gauge_expand||b.isPieType(a)&&c.pie_expand},i.shouldShowArcLabel=function(){var a=this,b=a.config,c=!0;return a.hasType("donut")?c=b.donut_label_show:a.hasType("pie")&&(c=b.pie_label_show),c},i.meetsArcLabelThreshold=function(a){var b=this,c=b.config,d=b.hasType("donut")?c.donut_label_threshold:c.pie_label_threshold;return a>=d},i.getArcLabelFormat=function(){var a=this,b=a.config,c=b.pie_label_format;return a.hasType("gauge")?c=b.gauge_label_format:a.hasType("donut")&&(c=b.donut_label_format),c},i.getArcTitle=function(){var a=this;return a.hasType("donut")?a.config.donut_title:""},i.updateTargetsForArc=function(a){var b,c,d=this,e=d.main,f=d.classChartArc.bind(d),g=d.classArcs.bind(d),h=d.classFocus.bind(d);b=e.select("."+l.chartArcs).selectAll("."+l.chartArc).data(d.pie(a)).attr("class",function(a){return f(a)+h(a.data)}),c=b.enter().append("g").attr("class",f),c.append("g").attr("class",g),c.append("text").attr("dy",d.hasType("gauge")?"-.1em":".35em").style("opacity",0).style("text-anchor","middle").style("pointer-events","none")},i.initArc=function(){var a=this;a.arcs=a.main.select("."+l.chart).append("g").attr("class",l.chartArcs).attr("transform",a.getTranslate("arc")),a.arcs.append("text").attr("class",l.chartArcsTitle).style("text-anchor","middle").text(a.getArcTitle())},i.redrawArc=function(a,b,c){var d,e=this,f=e.d3,g=e.config,h=e.main;d=h.selectAll("."+l.arcs).selectAll("."+l.arc).data(e.arcData.bind(e)),d.enter().append("path").attr("class",e.classArc.bind(e)).style("fill",function(a){return e.color(a.data)}).style("cursor",function(a){return g.interaction_enabled&&g.data_selection_isselectable(a)?"pointer":null}).style("opacity",0).each(function(a){e.isGaugeType(a.data)&&(a.startAngle=a.endAngle=g.gauge_startingAngle),this._current=a}),d.attr("transform",function(a){return!e.isGaugeType(a.data)&&c?"scale(0)":""}).style("opacity",function(a){return a===this._current?0:1}).on("mouseover",g.interaction_enabled?function(a){var b,c;e.transiting||(b=e.updateAngle(a),b&&(c=e.convertToArcData(b),e.expandArc(b.data.id),e.api.focus(b.data.id),e.toggleFocusLegend(b.data.id,!0),e.config.data_onmouseover(c,this)))}:null).on("mousemove",g.interaction_enabled?function(a){var b,c,d=e.updateAngle(a);d&&(b=e.convertToArcData(d),c=[b],e.showTooltip(c,this))}:null).on("mouseout",g.interaction_enabled?function(a){var b,c;e.transiting||(b=e.updateAngle(a),b&&(c=e.convertToArcData(b),e.unexpandArc(b.data.id),e.api.revert(),e.revertLegend(),e.hideTooltip(),e.config.data_onmouseout(c,this)))}:null).on("click",g.interaction_enabled?function(a,b){var c,d=e.updateAngle(a);d&&(c=e.convertToArcData(d),e.toggleShape&&e.toggleShape(this,c,b),e.config.data_onclick.call(e.api,c,this))}:null).each(function(){e.transiting=!0}).transition().duration(a).attrTween("d",function(a){var b,c=e.updateAngle(a);return c?(isNaN(this._current.startAngle)&&(this._current.startAngle=0),isNaN(this._current.endAngle)&&(this._current.endAngle=this._current.startAngle),b=f.interpolate(this._current,c),this._current=b(0),function(c){var d=b(c);return d.data=a.data,e.getArc(d,!0)}):function(){return"M 0 0"}}).attr("transform",c?"scale(1)":"").style("fill",function(a){return e.levelColor?e.levelColor(a.data.values[0].value):e.color(a.data.id)}).style("opacity",1).call(e.endall,function(){e.transiting=!1}),d.exit().transition().duration(b).style("opacity",0).remove(),h.selectAll("."+l.chartArc).select("text").style("opacity",0).attr("class",function(a){return e.isGaugeType(a.data)?l.gaugeValue:""}).text(e.textForArcLabel.bind(e)).attr("transform",e.transformForArcLabel.bind(e)).style("font-size",function(a){return e.isGaugeType(a.data)?Math.round(e.radius/5)+"px":""}).transition().duration(a).style("opacity",function(a){return e.isTargetToShow(a.data.id)&&e.isArcType(a.data)?1:0}),h.select("."+l.chartArcsTitle).style("opacity",e.hasType("donut")||e.hasType("gauge")?1:0),e.hasType("gauge")&&(e.arcs.select("."+l.chartArcsBackground).attr("d",function(){var a={data:[{value:g.gauge_max}],startAngle:g.gauge_startingAngle,endAngle:-1*g.gauge_startingAngle};return e.getArc(a,!0,!0)}),e.arcs.select("."+l.chartArcsGaugeUnit).attr("dy",".75em").text(g.gauge_label_show?g.gauge_units:""),e.arcs.select("."+l.chartArcsGaugeMin).attr("dx",-1*(e.innerRadius+(e.radius-e.innerRadius)/(g.gauge_fullCircle?1:2))+"px").attr("dy","1.2em").text(g.gauge_label_show?g.gauge_min:""),e.arcs.select("."+l.chartArcsGaugeMax).attr("dx",e.innerRadius+(e.radius-e.innerRadius)/(g.gauge_fullCircle?1:2)+"px").attr("dy","1.2em").text(g.gauge_label_show?g.gauge_max:""))},i.initGauge=function(){var a=this.arcs;this.hasType("gauge")&&(a.append("path").attr("class",l.chartArcsBackground),a.append("text").attr("class",l.chartArcsGaugeUnit).style("text-anchor","middle").style("pointer-events","none"),a.append("text").attr("class",l.chartArcsGaugeMin).style("text-anchor","middle").style("pointer-events","none"),a.append("text").attr("class",l.chartArcsGaugeMax).style("text-anchor","middle").style("pointer-events","none"))},i.getGaugeLabelHeight=function(){return this.config.gauge_label_show?20:0},i.initRegion=function(){var a=this;a.region=a.main.append("g").attr("clip-path",a.clipPath).attr("class",l.regions)},i.updateRegion=function(a){var b=this,c=b.config;b.region.style("visibility",b.hasArcType()?"hidden":"visible"),b.mainRegion=b.main.select("."+l.regions).selectAll("."+l.region).data(c.regions),b.mainRegion.enter().append("g").append("rect").style("fill-opacity",0),b.mainRegion.attr("class",b.classRegion.bind(b)),b.mainRegion.exit().transition().duration(a).style("opacity",0).remove()},i.redrawRegion=function(a){var b=this,c=b.mainRegion.selectAll("rect").each(function(){var a=b.d3.select(this.parentNode).datum();b.d3.select(this).datum(a)}),d=b.regionX.bind(b),e=b.regionY.bind(b),f=b.regionWidth.bind(b),g=b.regionHeight.bind(b);return[(a?c.transition():c).attr("x",d).attr("y",e).attr("width",f).attr("height",g).style("fill-opacity",function(a){return m(a.opacity)?a.opacity:.1})]},i.regionX=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated&&"start"in a?e(a.start):0:d.axis_rotated?0:"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0},i.regionY=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?0:"end"in a?e(a.end):0:d.axis_rotated&&"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0},i.regionWidth=function(a){var b,c=this,d=c.config,e=c.regionX(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated&&"end"in a?f(a.end):c.width:d.axis_rotated?c.width:"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.width,e>b?0:b-e},i.regionHeight=function(a){var b,c=this,d=c.config,e=this.regionY(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?c.height:"start"in a?f(a.start):c.height:d.axis_rotated&&"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.height,e>b?0:b-e},i.isRegionOnX=function(a){return!a.axis||"x"===a.axis},i.drag=function(a){var b,c,d,e,f,g,h,i,j=this,k=j.config,m=j.main,n=j.d3;j.hasArcType()||k.data_selection_enabled&&(k.zoom_enabled&&!j.zoom.altDomain||k.data_selection_multiple&&(b=j.dragStart[0],c=j.dragStart[1],d=a[0],e=a[1],f=Math.min(b,d),g=Math.max(b,d),h=k.data_selection_grouped?j.margin.top:Math.min(c,e),i=k.data_selection_grouped?j.height:Math.max(c,e),m.select("."+l.dragarea).attr("x",f).attr("y",h).attr("width",g-f).attr("height",i-h),m.selectAll("."+l.shapes).selectAll("."+l.shape).filter(function(a){return k.data_selection_isselectable(a)}).each(function(a,b){var c,d,e,k,m,o,p=n.select(this),q=p.classed(l.SELECTED),r=p.classed(l.INCLUDED),s=!1;if(p.classed(l.circle))c=1*p.attr("cx"),d=1*p.attr("cy"),m=j.togglePoint,s=c>f&&g>c&&d>h&&i>d;else{if(!p.classed(l.bar))return;o=z(this),c=o.x,d=o.y,e=o.width,k=o.height,m=j.togglePath,s=!(c>g||f>c+e||d>i||h>d+k)}s^r&&(p.classed(l.INCLUDED,!r),p.classed(l.SELECTED,!q),m.call(j,!q,p,a,b))})))},i.dragstart=function(a){var b=this,c=b.config;b.hasArcType()||c.data_selection_enabled&&(b.dragStart=a,b.main.select("."+l.chart).append("rect").attr("class",l.dragarea).style("opacity",.1),b.dragging=!0)},i.dragend=function(){var a=this,b=a.config;a.hasArcType()||b.data_selection_enabled&&(a.main.select("."+l.dragarea).transition().duration(100).style("opacity",0).remove(),a.main.selectAll("."+l.shape).classed(l.INCLUDED,!1),a.dragging=!1)},i.selectPoint=function(a,b,c){var d=this,e=d.config,f=(e.axis_rotated?d.circleY:d.circleX).bind(d),g=(e.axis_rotated?d.circleX:d.circleY).bind(d),h=d.pointSelectR.bind(d);e.data_onselected.call(d.api,b,a.node()),d.main.select("."+l.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+l.selectedCircle+"-"+c).data([b]).enter().append("circle").attr("class",function(){return d.generateClass(l.selectedCircle,c)}).attr("cx",f).attr("cy",g).attr("stroke",function(){return d.color(b)}).attr("r",function(a){return 1.4*d.pointSelectR(a)}).transition().duration(100).attr("r",h)},i.unselectPoint=function(a,b,c){var d=this;d.config.data_onunselected.call(d.api,b,a.node()),d.main.select("."+l.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+l.selectedCircle+"-"+c).transition().duration(100).attr("r",0).remove()},i.togglePoint=function(a,b,c,d){a?this.selectPoint(b,c,d):this.unselectPoint(b,c,d)},i.selectPath=function(a,b){var c=this;c.config.data_onselected.call(c,b,a.node()),c.config.interaction_brighten&&a.transition().duration(100).style("fill",function(){return c.d3.rgb(c.color(b)).brighter(.75)})},i.unselectPath=function(a,b){var c=this;c.config.data_onunselected.call(c,b,a.node()),c.config.interaction_brighten&&a.transition().duration(100).style("fill",function(){return c.color(b)})},i.togglePath=function(a,b,c,d){a?this.selectPath(b,c,d):this.unselectPath(b,c,d)},i.getToggle=function(a,b){var c,d=this;return"circle"===a.nodeName?c=d.isStepType(b)?function(){}:d.togglePoint:"path"===a.nodeName&&(c=d.togglePath),c},i.toggleShape=function(a,b,c){var d=this,e=d.d3,f=d.config,g=e.select(a),h=g.classed(l.SELECTED),i=d.getToggle(a,b).bind(d);f.data_selection_enabled&&f.data_selection_isselectable(b)&&(f.data_selection_multiple||d.main.selectAll("."+l.shapes+(f.data_selection_grouped?d.getTargetSelectorSuffix(b.id):"")).selectAll("."+l.shape).each(function(a,b){var c=e.select(this);c.classed(l.SELECTED)&&i(!1,c.classed(l.SELECTED,!1),a,b)}),g.classed(l.SELECTED,!h),i(!h,g,b,c))},i.initBrush=function(){var a=this,b=a.d3;a.brush=b.svg.brush().on("brush",function(){a.redrawForBrush()}),a.brush.update=function(){return a.context&&a.context.select("."+l.brush).call(this),this},a.brush.scale=function(b){return a.config.axis_rotated?this.y(b):this.x(b)}},i.initSubchart=function(){var a=this,b=a.config,c=a.context=a.svg.append("g").attr("transform",a.getTranslate("context")),d=b.subchart_show?"visible":"hidden";c.style("visibility",d),c.append("g").attr("clip-path",a.clipPathForSubchart).attr("class",l.chart),c.select("."+l.chart).append("g").attr("class",l.chartBars),c.select("."+l.chart).append("g").attr("class",l.chartLines),c.append("g").attr("clip-path",a.clipPath).attr("class",l.brush).call(a.brush),a.axes.subx=c.append("g").attr("class",l.axisX).attr("transform",a.getTranslate("subx")).attr("clip-path",b.axis_rotated?"":a.clipPathForXAxis).style("visibility",b.subchart_axis_x_show?d:"hidden")},i.updateTargetsForSubchart=function(a){var b,c,d,e,f=this,g=f.context,h=f.config,i=f.classChartBar.bind(f),j=f.classBars.bind(f),k=f.classChartLine.bind(f),m=f.classLines.bind(f),n=f.classAreas.bind(f);h.subchart_show&&(e=g.select("."+l.chartBars).selectAll("."+l.chartBar).data(a).attr("class",i),d=e.enter().append("g").style("opacity",0).attr("class",i),d.append("g").attr("class",j),c=g.select("."+l.chartLines).selectAll("."+l.chartLine).data(a).attr("class",k),b=c.enter().append("g").style("opacity",0).attr("class",k),b.append("g").attr("class",m),b.append("g").attr("class",n),g.selectAll("."+l.brush+" rect").attr(h.axis_rotated?"width":"height",h.axis_rotated?f.width2:f.height2))},i.updateBarForSubchart=function(a){var b=this;b.contextBar=b.context.selectAll("."+l.bars).selectAll("."+l.bar).data(b.barData.bind(b)),b.contextBar.enter().append("path").attr("class",b.classBar.bind(b)).style("stroke","none").style("fill",b.color),b.contextBar.style("opacity",b.initialOpacity.bind(b)),b.contextBar.exit().transition().duration(a).style("opacity",0).remove()},i.redrawBarForSubchart=function(a,b,c){(b?this.contextBar.transition(Math.random().toString()).duration(c):this.contextBar).attr("d",a).style("opacity",1)},i.updateLineForSubchart=function(a){var b=this;b.contextLine=b.context.selectAll("."+l.lines).selectAll("."+l.line).data(b.lineData.bind(b)),b.contextLine.enter().append("path").attr("class",b.classLine.bind(b)).style("stroke",b.color),b.contextLine.style("opacity",b.initialOpacity.bind(b)),b.contextLine.exit().transition().duration(a).style("opacity",0).remove()},i.redrawLineForSubchart=function(a,b,c){(b?this.contextLine.transition(Math.random().toString()).duration(c):this.contextLine).attr("d",a).style("opacity",1)},i.updateAreaForSubchart=function(a){var b=this,c=b.d3;b.contextArea=b.context.selectAll("."+l.areas).selectAll("."+l.area).data(b.lineData.bind(b)),b.contextArea.enter().append("path").attr("class",b.classArea.bind(b)).style("fill",b.color).style("opacity",function(){return b.orgAreaOpacity=+c.select(this).style("opacity"),0}),b.contextArea.style("opacity",0),b.contextArea.exit().transition().duration(a).style("opacity",0).remove()},i.redrawAreaForSubchart=function(a,b,c){(b?this.contextArea.transition(Math.random().toString()).duration(c):this.contextArea).attr("d",a).style("fill",this.color).style("opacity",this.orgAreaOpacity)},i.redrawSubchart=function(a,b,c,d,e,f,g){var h,i,j,k=this,l=k.d3,m=k.config;k.context.style("visibility",m.subchart_show?"visible":"hidden"),m.subchart_show&&(l.event&&"zoom"===l.event.type&&k.brush.extent(k.x.orgDomain()).update(),a&&(k.brush.empty()||k.brush.extent(k.x.orgDomain()).update(),h=k.generateDrawArea(e,!0),i=k.generateDrawBar(f,!0),j=k.generateDrawLine(g,!0),k.updateBarForSubchart(c),k.updateLineForSubchart(c),k.updateAreaForSubchart(c),k.redrawBarForSubchart(i,c,c),k.redrawLineForSubchart(j,c,c),k.redrawAreaForSubchart(h,c,c)))},i.redrawForBrush=function(){var a=this,b=a.x;a.redraw({withTransition:!1,withY:a.config.zoom_rescale,withSubchart:!1,withUpdateXDomain:!0,withDimension:!1}),a.config.subchart_onbrush.call(a.api,b.orgDomain())},i.transformContext=function(a,b){var c,d=this;b&&b.axisSubX?c=b.axisSubX:(c=d.context.select("."+l.axisX),a&&(c=c.transition())),d.context.attr("transform",d.getTranslate("context")),c.attr("transform",d.getTranslate("subx"))},i.getDefaultExtent=function(){var a=this,b=a.config,c=n(b.axis_x_extent)?b.axis_x_extent(a.getXDomain(a.data.targets)):b.axis_x_extent;return a.isTimeSeries()&&(c=[a.parseDate(c[0]),a.parseDate(c[1])]),c},i.initZoom=function(){var a,b=this,c=b.d3,d=b.config;b.zoom=c.behavior.zoom().on("zoomstart",function(){a=c.event.sourceEvent,b.zoom.altDomain=c.event.sourceEvent.altKey?b.x.orgDomain():null,d.zoom_onzoomstart.call(b.api,c.event.sourceEvent)}).on("zoom",function(){b.redrawForZoom.call(b)}).on("zoomend",function(){var e=c.event.sourceEvent;e&&a.clientX===e.clientX&&a.clientY===e.clientY||(b.redrawEventRect(),b.updateZoom(),d.zoom_onzoomend.call(b.api,b.x.orgDomain()))}),b.zoom.scale=function(a){return d.axis_rotated?this.y(a):this.x(a)},b.zoom.orgScaleExtent=function(){var a=d.zoom_extent?d.zoom_extent:[1,10];return[a[0],Math.max(b.getMaxDataCount()/a[1],a[1])]},b.zoom.updateScaleExtent=function(){var a=t(b.x.orgDomain())/t(b.getZoomDomain()),c=this.orgScaleExtent();return this.scaleExtent([c[0]*a,c[1]*a]),this}},i.getZoomDomain=function(){var a=this,b=a.config,c=a.d3,d=c.min([a.orgXDomain[0],b.zoom_x_min]),e=c.max([a.orgXDomain[1],b.zoom_x_max]);return[d,e]},i.updateZoom=function(){var a=this,b=a.config.zoom_enabled?a.zoom:function(){};a.main.select("."+l.zoomRect).call(b).on("dblclick.zoom",null),a.main.selectAll("."+l.eventRect).call(b).on("dblclick.zoom",null)},i.redrawForZoom=function(){var a=this,b=a.d3,c=a.config,d=a.zoom,e=a.x;if(c.zoom_enabled&&0!==a.filterTargetsToShow(a.data.targets).length){if("mousemove"===b.event.sourceEvent.type&&d.altDomain)return e.domain(d.altDomain),void d.scale(e).updateScaleExtent();a.isCategorized()&&e.orgDomain()[0]===a.orgXDomain[0]&&e.domain([a.orgXDomain[0]-1e-10,e.orgDomain()[1]]),a.redraw({withTransition:!1,withY:c.zoom_rescale,withSubchart:!1,withEventRect:!1,withDimension:!1}),"mousemove"===b.event.sourceEvent.type&&(a.cancelClick=!0),c.zoom_onzoom.call(a.api,e.orgDomain())}},i.generateColor=function(){var a=this,b=a.config,c=a.d3,d=b.data_colors,e=v(b.color_pattern)?b.color_pattern:c.scale.category10().range(),f=b.data_color,g=[];return function(a){var b,c=a.id||a.data&&a.data.id||a;return d[c]instanceof Function?b=d[c](a):d[c]?b=d[c]:(g.indexOf(c)<0&&g.push(c),b=e[g.indexOf(c)%e.length],d[c]=b),f instanceof Function?f(b,a):b}},i.generateLevelColor=function(){var a=this,b=a.config,c=b.color_pattern,d=b.color_threshold,e="value"===d.unit,f=d.values&&d.values.length?d.values:[],g=d.max||100;return v(b.color_threshold)?function(a){var b,d,h=c[c.length-1];for(b=0;b=0?l.focused:"")},i.classDefocused=function(a){return" "+(this.defocusedTargetIds.indexOf(a.id)>=0?l.defocused:"")},i.classChartText=function(a){return l.chartText+this.classTarget(a.id)},i.classChartLine=function(a){return l.chartLine+this.classTarget(a.id)},i.classChartBar=function(a){return l.chartBar+this.classTarget(a.id)},i.classChartArc=function(a){return l.chartArc+this.classTarget(a.data.id)},i.getTargetSelectorSuffix=function(a){return a||0===a?("-"+a).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g,"-"):""},i.selectorTarget=function(a,b){return(b||"")+"."+l.target+this.getTargetSelectorSuffix(a)},i.selectorTargets=function(a,b){var c=this;return a=a||[],a.length?a.map(function(a){return c.selectorTarget(a,b)}):null},i.selectorLegend=function(a){return"."+l.legendItem+this.getTargetSelectorSuffix(a)},i.selectorLegends=function(a){var b=this;return a&&a.length?a.map(function(a){return b.selectorLegend(a)}):null};var m=i.isValue=function(a){return a||0===a},n=i.isFunction=function(a){return"function"==typeof a},o=i.isString=function(a){return"string"==typeof a},p=i.isUndefined=function(a){return"undefined"==typeof a},q=i.isDefined=function(a){return"undefined"!=typeof a},r=i.ceil10=function(a){return 10*Math.ceil(a/10)},s=i.asHalfPixel=function(a){return Math.ceil(a)+.5},t=i.diffDomain=function(a){return a[1]-a[0]},u=i.isEmpty=function(a){return"undefined"==typeof a||null===a||o(a)&&0===a.length||"object"==typeof a&&0===Object.keys(a).length},v=i.notEmpty=function(a){return!i.isEmpty(a)},w=i.getOption=function(a,b,c){return q(a[b])?a[b]:c},x=i.hasValue=function(a,b){var c=!1;return Object.keys(a).forEach(function(d){a[d]===b&&(c=!0)}),c},y=i.sanitise=function(a){return"string"==typeof a?a.replace(//g,">"):a},z=i.getPathBox=function(a){var b=a.getBoundingClientRect(),c=[a.pathSegList.getItem(0),a.pathSegList.getItem(1)],d=c[0].x,e=Math.min(c[0].y,c[1].y);return{x:d,y:e,width:b.width,height:b.height}};h.focus=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a.filter(c.isTargetToShow,c))),this.revert(),this.defocus(),b.classed(l.focused,!0).classed(l.defocused,!1), -c.hasArcType()&&c.expandArc(a),c.toggleFocusLegend(a,!0),c.focusedTargetIds=a,c.defocusedTargetIds=c.defocusedTargetIds.filter(function(b){return a.indexOf(b)<0})},h.defocus=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a.filter(c.isTargetToShow,c))),b.classed(l.focused,!1).classed(l.defocused,!0),c.hasArcType()&&c.unexpandArc(a),c.toggleFocusLegend(a,!1),c.focusedTargetIds=c.focusedTargetIds.filter(function(b){return a.indexOf(b)<0}),c.defocusedTargetIds=a},h.revert=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a)),b.classed(l.focused,!1).classed(l.defocused,!1),c.hasArcType()&&c.unexpandArc(a),c.config.legend_show&&(c.showLegend(a.filter(c.isLegendToShow.bind(c))),c.legend.selectAll(c.selectorLegends(a)).filter(function(){return c.d3.select(this).classed(l.legendItemFocused)}).classed(l.legendItemFocused,!1)),c.focusedTargetIds=[],c.defocusedTargetIds=[]},h.show=function(a,b){var c,d=this.internal;a=d.mapToTargetIds(a),b=b||{},d.removeHiddenTargetIds(a),c=d.svg.selectAll(d.selectorTargets(a)),c.transition().style("opacity",1,"important").call(d.endall,function(){c.style("opacity",null).style("opacity",1)}),b.withLegend&&d.showLegend(a),d.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},h.hide=function(a,b){var c,d=this.internal;a=d.mapToTargetIds(a),b=b||{},d.addHiddenTargetIds(a),c=d.svg.selectAll(d.selectorTargets(a)),c.transition().style("opacity",0,"important").call(d.endall,function(){c.style("opacity",null).style("opacity",0)}),b.withLegend&&d.hideLegend(a),d.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},h.toggle=function(a,b){var c=this,d=this.internal;d.mapToTargetIds(a).forEach(function(a){d.isTargetToShow(a)?c.hide(a,b):c.show(a,b)})},h.zoom=function(a){var b=this.internal;return a&&(b.isTimeSeries()&&(a=a.map(function(a){return b.parseDate(a)})),b.brush.extent(a),b.redraw({withUpdateXDomain:!0,withY:b.config.zoom_rescale}),b.config.zoom_onzoom.call(this,b.x.orgDomain())),b.brush.extent()},h.zoom.enable=function(a){var b=this.internal;b.config.zoom_enabled=a,b.updateAndRedraw()},h.unzoom=function(){var a=this.internal;a.brush.clear().update(),a.redraw({withUpdateXDomain:!0})},h.zoom.max=function(a){var b=this.internal,c=b.config,d=b.d3;return 0===a||a?void(c.zoom_x_max=d.max([b.orgXDomain[1],a])):c.zoom_x_max},h.zoom.min=function(a){var b=this.internal,c=b.config,d=b.d3;return 0===a||a?void(c.zoom_x_min=d.min([b.orgXDomain[0],a])):c.zoom_x_min},h.zoom.range=function(a){return arguments.length?(q(a.max)&&this.domain.max(a.max),void(q(a.min)&&this.domain.min(a.min))):{max:this.domain.max(),min:this.domain.min()}},h.load=function(a){var b=this.internal,c=b.config;return a.xs&&b.addXs(a.xs),"names"in a&&h.data.names.bind(this)(a.names),"classes"in a&&Object.keys(a.classes).forEach(function(b){c.data_classes[b]=a.classes[b]}),"categories"in a&&b.isCategorized()&&(c.axis_x_categories=a.categories),"axes"in a&&Object.keys(a.axes).forEach(function(b){c.data_axes[b]=a.axes[b]}),"colors"in a&&Object.keys(a.colors).forEach(function(b){c.data_colors[b]=a.colors[b]}),"cacheIds"in a&&b.hasCaches(a.cacheIds)?void b.load(b.getCaches(a.cacheIds),a.done):void("unload"in a?b.unload(b.mapToTargetIds("boolean"==typeof a.unload&&a.unload?null:a.unload),function(){b.loadFromArgs(a)}):b.loadFromArgs(a))},h.unload=function(a){var b=this.internal;a=a||{},a instanceof Array?a={ids:a}:"string"==typeof a&&(a={ids:[a]}),b.unload(b.mapToTargetIds(a.ids),function(){b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0}),a.done&&a.done()})},h.flow=function(a){var b,c,d,e,f,g,h,i,j=this.internal,k=[],l=j.getMaxDataCount(),n=0,o=0;if(a.json)c=j.convertJsonToData(a.json,a.keys);else if(a.rows)c=j.convertRowsToData(a.rows);else{if(!a.columns)return;c=j.convertColumnsToData(a.columns)}b=j.convertDataToTargets(c,!0),j.data.targets.forEach(function(a){var c,d,e=!1;for(c=0;cd;d++)b[c].values[d].index=o+d,j.isTimeSeries()||(b[c].values[d].x=o+d);a.values=a.values.concat(b[c].values),b.splice(c,1);break}e||k.push(a.id)}),j.data.targets.forEach(function(a){var b,c;for(b=0;bc;c++)a.values.push({id:a.id,index:o+c,x:j.isTimeSeries()?j.getOtherTargetX(o+c):o+c,value:null})}),j.data.targets.length&&b.forEach(function(a){var b,c=[];for(b=j.data.targets[0].values[0].index;o>b;b++)c.push({id:a.id,index:b,x:j.isTimeSeries()?j.getOtherTargetX(b):b,value:null});a.values.forEach(function(a){a.index+=o,j.isTimeSeries()||(a.x+=o)}),a.values=c.concat(a.values)}),j.data.targets=j.data.targets.concat(b),d=j.getMaxDataCount(),f=j.data.targets[0],g=f.values[0],q(a.to)?(n=0,i=j.isTimeSeries()?j.parseDate(a.to):a.to,f.values.forEach(function(a){a.x1?f.values[f.values.length-1].x-g.x:g.x-j.getXDomain(j.data.targets)[0]:1,e=[g.x-h,g.x],j.updateXDomain(null,!0,!0,!1,e)),j.updateTargets(j.data.targets),j.redraw({flow:{index:g.index,length:n,duration:m(a.duration)?a.duration:j.config.transition_duration,done:a.done,orgDataCount:l},withLegend:!0,withTransition:l>1,withTrimXDomain:!1,withUpdateXAxis:!0})},i.generateFlow=function(a){var b=this,c=b.config,d=b.d3;return function(){var e,f,g,h=a.targets,i=a.flow,j=a.drawBar,k=a.drawLine,m=a.drawArea,n=a.cx,o=a.cy,p=a.xv,q=a.xForText,r=a.yForText,s=a.duration,u=1,v=i.index,w=i.length,x=b.getValueOnIndex(b.data.targets[0].values,v),y=b.getValueOnIndex(b.data.targets[0].values,v+w),z=b.x.domain(),A=i.duration||s,B=i.done||function(){},C=b.generateWait(),D=b.xgrid||d.selectAll([]),E=b.xgridLines||d.selectAll([]),F=b.mainRegion||d.selectAll([]),G=b.mainText||d.selectAll([]),H=b.mainBar||d.selectAll([]),I=b.mainLine||d.selectAll([]),J=b.mainArea||d.selectAll([]),K=b.mainCircle||d.selectAll([]);b.flowing=!0,b.data.targets.forEach(function(a){a.values.splice(0,w)}),g=b.updateXDomain(h,!0,!0),b.updateXGrid&&b.updateXGrid(!0),i.orgDataCount?e=1===i.orgDataCount||(x&&x.x)===(y&&y.x)?b.x(z[0])-b.x(g[0]):b.isTimeSeries()?b.x(z[0])-b.x(g[0]):b.x(x.x)-b.x(y.x):1!==b.data.targets[0].values.length?e=b.x(z[0])-b.x(g[0]):b.isTimeSeries()?(x=b.getValueOnIndex(b.data.targets[0].values,0),y=b.getValueOnIndex(b.data.targets[0].values,b.data.targets[0].values.length-1),e=b.x(x.x)-b.x(y.x)):e=t(g)/2,u=t(z)/t(g),f="translate("+e+",0) scale("+u+",1)",b.hideXGridFocus(),d.transition().ease("linear").duration(A).each(function(){C.add(b.axes.x.transition().call(b.xAxis)),C.add(H.transition().attr("transform",f)),C.add(I.transition().attr("transform",f)),C.add(J.transition().attr("transform",f)),C.add(K.transition().attr("transform",f)),C.add(G.transition().attr("transform",f)),C.add(F.filter(b.isRegionOnX).transition().attr("transform",f)),C.add(D.transition().attr("transform",f)),C.add(E.transition().attr("transform",f))}).call(C,function(){var a,d=[],e=[],f=[];if(w){for(a=0;w>a;a++)d.push("."+l.shape+"-"+(v+a)),e.push("."+l.text+"-"+(v+a)),f.push("."+l.eventRect+"-"+(v+a));b.svg.selectAll("."+l.shapes).selectAll(d).remove(),b.svg.selectAll("."+l.texts).selectAll(e).remove(),b.svg.selectAll("."+l.eventRects).selectAll(f).remove(),b.svg.select("."+l.xgrid).remove()}D.attr("transform",null).attr(b.xgridAttr),E.attr("transform",null),E.select("line").attr("x1",c.axis_rotated?0:p).attr("x2",c.axis_rotated?b.width:p),E.select("text").attr("x",c.axis_rotated?b.width:0).attr("y",p),H.attr("transform",null).attr("d",j),I.attr("transform",null).attr("d",k),J.attr("transform",null).attr("d",m),K.attr("transform",null).attr("cx",n).attr("cy",o),G.attr("transform",null).attr("x",q).attr("y",r).style("fill-opacity",b.opacityForText.bind(b)),F.attr("transform",null),F.select("rect").filter(b.isRegionOnX).attr("x",b.regionX.bind(b)).attr("width",b.regionWidth.bind(b)),c.interaction_enabled&&b.redrawEventRect(),B(),b.flowing=!1})}},h.selected=function(a){var b=this.internal,c=b.d3;return c.merge(b.main.selectAll("."+l.shapes+b.getTargetSelectorSuffix(a)).selectAll("."+l.shape).filter(function(){return c.select(this).classed(l.SELECTED)}).map(function(a){return a.map(function(a){var b=a.__data__;return b.data?b.data:b})}))},h.select=function(a,b,c){var d=this.internal,e=d.d3,f=d.config;f.data_selection_enabled&&d.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(g,h){var i=e.select(this),j=g.data?g.data.id:g.id,k=d.getToggle(this,g).bind(d),m=f.data_selection_grouped||!a||a.indexOf(j)>=0,n=!b||b.indexOf(h)>=0,o=i.classed(l.SELECTED);i.classed(l.line)||i.classed(l.area)||(m&&n?f.data_selection_isselectable(g)&&!o&&k(!0,i.classed(l.SELECTED,!0),g,h):q(c)&&c&&o&&k(!1,i.classed(l.SELECTED,!1),g,h))})},h.unselect=function(a,b){var c=this.internal,d=c.d3,e=c.config;e.data_selection_enabled&&c.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(f,g){var h=d.select(this),i=f.data?f.data.id:f.id,j=c.getToggle(this,f).bind(c),k=e.data_selection_grouped||!a||a.indexOf(i)>=0,m=!b||b.indexOf(g)>=0,n=h.classed(l.SELECTED);h.classed(l.line)||h.classed(l.area)||k&&m&&e.data_selection_isselectable(f)&&n&&j(!1,h.classed(l.SELECTED,!1),f,g)})},h.transform=function(a,b){var c=this.internal,d=["pie","donut"].indexOf(a)>=0?{withTransform:!0}:null;c.transformTo(b,a,d)},i.transformTo=function(a,b,c){var d=this,e=!d.hasArcType(),f=c||{withTransitionForAxis:e};f.withTransitionForTransform=!1,d.transiting=!1,d.setTargetType(a,b),d.updateTargets(d.data.targets),d.updateAndRedraw(f)},h.groups=function(a){var b=this.internal,c=b.config;return p(a)?c.data_groups:(c.data_groups=a,b.redraw(),c.data_groups)},h.xgrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_x_lines=a,b.redrawWithoutRescale(),c.grid_x_lines):c.grid_x_lines},h.xgrids.add=function(a){var b=this.internal;return this.xgrids(b.config.grid_x_lines.concat(a?a:[]))},h.xgrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!0)},h.ygrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_y_lines=a,b.redrawWithoutRescale(),c.grid_y_lines):c.grid_y_lines},h.ygrids.add=function(a){var b=this.internal;return this.ygrids(b.config.grid_y_lines.concat(a?a:[]))},h.ygrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!1)},h.regions=function(a){var b=this.internal,c=b.config;return a?(c.regions=a,b.redrawWithoutRescale(),c.regions):c.regions},h.regions.add=function(a){var b=this.internal,c=b.config;return a?(c.regions=c.regions.concat(a),b.redrawWithoutRescale(),c.regions):c.regions},h.regions.remove=function(a){var b,c,d,e=this.internal,f=e.config;return a=a||{},b=e.getOption(a,"duration",f.transition_duration),c=e.getOption(a,"classes",[l.region]),d=e.main.select("."+l.regions).selectAll(c.map(function(a){return"."+a})),(b?d.transition().duration(b):d).style("opacity",0).remove(),f.regions=f.regions.filter(function(a){var b=!1;return a["class"]?(a["class"].split(" ").forEach(function(a){c.indexOf(a)>=0&&(b=!0)}),!b):!0}),f.regions},h.data=function(a){var b=this.internal.data.targets;return"undefined"==typeof a?b:b.filter(function(b){return[].concat(a).indexOf(b.id)>=0})},h.data.shown=function(a){return this.internal.filterTargetsToShow(this.data(a))},h.data.values=function(a){var b,c=null;return a&&(b=this.data(a),c=b[0]?b[0].values.map(function(a){return a.value}):null),c},h.data.names=function(a){return this.internal.clearLegendItemTextBoxCache(),this.internal.updateDataAttributes("names",a)},h.data.colors=function(a){return this.internal.updateDataAttributes("colors",a)},h.data.axes=function(a){return this.internal.updateDataAttributes("axes",a)},h.category=function(a,b){var c=this.internal,d=c.config;return arguments.length>1&&(d.axis_x_categories[a]=b,c.redraw()),d.axis_x_categories[a]},h.categories=function(a){var b=this.internal,c=b.config;return arguments.length?(c.axis_x_categories=a,b.redraw(),c.axis_x_categories):c.axis_x_categories},h.color=function(a){var b=this.internal;return b.color(a)},h.x=function(a){var b=this.internal;return arguments.length&&(b.updateTargetX(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.xs=function(a){var b=this.internal;return arguments.length&&(b.updateTargetXs(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.axis=function(){},h.axis.labels=function(a){var b=this.internal;arguments.length&&(Object.keys(a).forEach(function(c){b.axis.setLabelText(c,a[c])}),b.axis.updateLabels())},h.axis.max=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_max=a.x),m(a.y)&&(c.axis_y_max=a.y),m(a.y2)&&(c.axis_y2_max=a.y2)):c.axis_y_max=c.axis_y2_max=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_max,y:c.axis_y_max,y2:c.axis_y2_max}},h.axis.min=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_min=a.x),m(a.y)&&(c.axis_y_min=a.y),m(a.y2)&&(c.axis_y2_min=a.y2)):c.axis_y_min=c.axis_y2_min=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_min,y:c.axis_y_min,y2:c.axis_y2_min}},h.axis.range=function(a){return arguments.length?(q(a.max)&&this.axis.max(a.max),void(q(a.min)&&this.axis.min(a.min))):{max:this.axis.max(),min:this.axis.min()}},h.legend=function(){},h.legend.show=function(a){var b=this.internal;b.showLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.legend.hide=function(a){var b=this.internal;b.hideLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.resize=function(a){var b=this.internal,c=b.config;c.size_width=a?a.width:null,c.size_height=a?a.height:null,this.flush()},h.flush=function(){var a=this.internal;a.updateAndRedraw({withLegend:!0,withTransition:!1,withTransitionForTransform:!1})},h.destroy=function(){var b=this.internal;if(a.clearInterval(b.intervalForObserveInserted),void 0!==b.resizeTimeout&&a.clearTimeout(b.resizeTimeout),a.detachEvent)a.detachEvent("onresize",b.resizeFunction);else if(a.removeEventListener)a.removeEventListener("resize",b.resizeFunction);else{var c=a.onresize;c&&c.add&&c.remove&&c.remove(b.resizeFunction)}return b.selectChart.classed("c3",!1).html(""),Object.keys(b).forEach(function(a){b[a]=null}),null},h.tooltip=function(){},h.tooltip.show=function(a){var b,c,d=this.internal;a.mouse&&(c=a.mouse),a.data?d.isMultipleX()?(c=[d.x(a.data.x),d.getYScale(a.data.id)(a.data.value)],b=null):b=m(a.data.index)?a.data.index:d.getIndexByX(a.data.x):"undefined"!=typeof a.x?b=d.getIndexByX(a.x):"undefined"!=typeof a.index&&(b=a.index),d.dispatchEvent("mouseover",b,c),d.dispatchEvent("mousemove",b,c),d.config.tooltip_onshow.call(d,a.data)},h.tooltip.hide=function(){this.internal.dispatchEvent("mouseout",0),this.internal.config.tooltip_onhide.call(this)};var A;i.isSafari=function(){var b=a.navigator.userAgent;return b.indexOf("Safari")>=0&&b.indexOf("Chrome")<0},i.isChrome=function(){var b=a.navigator.userAgent;return b.indexOf("Chrome")>=0},Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),function(){"SVGPathSeg"in a||(a.SVGPathSeg=function(a,b,c){this.pathSegType=a,this.pathSegTypeAsLetter=b,this._owningPathSegList=c},SVGPathSeg.PATHSEG_UNKNOWN=0,SVGPathSeg.PATHSEG_CLOSEPATH=1,SVGPathSeg.PATHSEG_MOVETO_ABS=2,SVGPathSeg.PATHSEG_MOVETO_REL=3,SVGPathSeg.PATHSEG_LINETO_ABS=4,SVGPathSeg.PATHSEG_LINETO_REL=5,SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS=6,SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL=7,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS=8,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL=9,SVGPathSeg.PATHSEG_ARC_ABS=10,SVGPathSeg.PATHSEG_ARC_REL=11,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS=12,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL=13,SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS=14,SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL=15,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS=16,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL=17,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS=18,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL=19,SVGPathSeg.prototype._segmentChanged=function(){this._owningPathSegList&&this._owningPathSegList.segmentChanged(this)},a.SVGPathSegClosePath=function(a){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CLOSEPATH,"z",a)},SVGPathSegClosePath.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegClosePath.prototype.toString=function(){return"[object SVGPathSegClosePath]"},SVGPathSegClosePath.prototype._asPathString=function(){return this.pathSegTypeAsLetter},SVGPathSegClosePath.prototype.clone=function(){return new SVGPathSegClosePath(void 0)},a.SVGPathSegMovetoAbs=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_MOVETO_ABS,"M",a),this._x=b,this._y=c},SVGPathSegMovetoAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegMovetoAbs.prototype.toString=function(){return"[object SVGPathSegMovetoAbs]"},SVGPathSegMovetoAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegMovetoAbs.prototype.clone=function(){return new SVGPathSegMovetoAbs(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegMovetoAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegMovetoAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegMovetoRel=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_MOVETO_REL,"m",a),this._x=b,this._y=c},SVGPathSegMovetoRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegMovetoRel.prototype.toString=function(){return"[object SVGPathSegMovetoRel]"},SVGPathSegMovetoRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegMovetoRel.prototype.clone=function(){return new SVGPathSegMovetoRel(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegMovetoRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegMovetoRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoAbs=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_ABS,"L",a),this._x=b,this._y=c},SVGPathSegLinetoAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoAbs.prototype.toString=function(){return"[object SVGPathSegLinetoAbs]"},SVGPathSegLinetoAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegLinetoAbs.prototype.clone=function(){return new SVGPathSegLinetoAbs(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegLinetoAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegLinetoAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoRel=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_REL,"l",a),this._x=b,this._y=c},SVGPathSegLinetoRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoRel.prototype.toString=function(){return"[object SVGPathSegLinetoRel]"},SVGPathSegLinetoRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegLinetoRel.prototype.clone=function(){return new SVGPathSegLinetoRel(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegLinetoRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegLinetoRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicAbs=function(a,b,c,d,e,f,g){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS,"C",a),this._x=b,this._y=c,this._x1=d,this._y1=e,this._x2=f,this._y2=g},SVGPathSegCurvetoCubicAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicAbs]"},SVGPathSegCurvetoCubicAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicAbs.prototype.clone=function(){return new SVGPathSegCurvetoCubicAbs(void 0,this._x,this._y,this._x1,this._y1,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicRel=function(a,b,c,d,e,f,g){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL,"c",a),this._x=b,this._y=c,this._x1=d,this._y1=e,this._x2=f,this._y2=g},SVGPathSegCurvetoCubicRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicRel.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicRel]"},SVGPathSegCurvetoCubicRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicRel.prototype.clone=function(){return new SVGPathSegCurvetoCubicRel(void 0,this._x,this._y,this._x1,this._y1,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticAbs=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS,"Q",a),this._x=b,this._y=c,this._x1=d,this._y1=e},SVGPathSegCurvetoQuadraticAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticAbs]"},SVGPathSegCurvetoQuadraticAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticAbs.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticAbs(void 0,this._x,this._y,this._x1,this._y1)},Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticRel=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL,"q",a),this._x=b,this._y=c,this._x1=d,this._y1=e},SVGPathSegCurvetoQuadraticRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticRel.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticRel]"},SVGPathSegCurvetoQuadraticRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticRel.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticRel(void 0,this._x,this._y,this._x1,this._y1)},Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegArcAbs=function(a,b,c,d,e,f,g,h){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_ARC_ABS,"A",a),this._x=b,this._y=c,this._r1=d,this._r2=e,this._angle=f,this._largeArcFlag=g,this._sweepFlag=h},SVGPathSegArcAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegArcAbs.prototype.toString=function(){return"[object SVGPathSegArcAbs]"},SVGPathSegArcAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._r1+" "+this._r2+" "+this._angle+" "+(this._largeArcFlag?"1":"0")+" "+(this._sweepFlag?"1":"0")+" "+this._x+" "+this._y},SVGPathSegArcAbs.prototype.clone=function(){return new SVGPathSegArcAbs(void 0,this._x,this._y,this._r1,this._r2,this._angle,this._largeArcFlag,this._sweepFlag)},Object.defineProperty(SVGPathSegArcAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"r1",{get:function(){return this._r1},set:function(a){this._r1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"r2",{get:function(){return this._r2},set:function(a){this._r2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"angle",{get:function(){return this._angle},set:function(a){this._angle=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"largeArcFlag",{get:function(){return this._largeArcFlag},set:function(a){this._largeArcFlag=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"sweepFlag",{get:function(){return this._sweepFlag},set:function(a){this._sweepFlag=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegArcRel=function(a,b,c,d,e,f,g,h){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_ARC_REL,"a",a),this._x=b,this._y=c,this._r1=d,this._r2=e,this._angle=f,this._largeArcFlag=g,this._sweepFlag=h},SVGPathSegArcRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegArcRel.prototype.toString=function(){return"[object SVGPathSegArcRel]"},SVGPathSegArcRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._r1+" "+this._r2+" "+this._angle+" "+(this._largeArcFlag?"1":"0")+" "+(this._sweepFlag?"1":"0")+" "+this._x+" "+this._y},SVGPathSegArcRel.prototype.clone=function(){return new SVGPathSegArcRel(void 0,this._x,this._y,this._r1,this._r2,this._angle,this._largeArcFlag,this._sweepFlag)},Object.defineProperty(SVGPathSegArcRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"r1",{get:function(){return this._r1},set:function(a){this._r1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"r2",{get:function(){return this._r2},set:function(a){this._r2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"angle",{get:function(){return this._angle},set:function(a){this._angle=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"largeArcFlag",{get:function(){return this._largeArcFlag},set:function(a){this._largeArcFlag=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"sweepFlag",{get:function(){return this._sweepFlag},set:function(a){this._sweepFlag=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoHorizontalAbs=function(a,b){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS,"H",a),this._x=b},SVGPathSegLinetoHorizontalAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoHorizontalAbs.prototype.toString=function(){return"[object SVGPathSegLinetoHorizontalAbs]"},SVGPathSegLinetoHorizontalAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x},SVGPathSegLinetoHorizontalAbs.prototype.clone=function(){return new SVGPathSegLinetoHorizontalAbs(void 0,this._x)},Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoHorizontalRel=function(a,b){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL,"h",a),this._x=b},SVGPathSegLinetoHorizontalRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoHorizontalRel.prototype.toString=function(){return"[object SVGPathSegLinetoHorizontalRel]"},SVGPathSegLinetoHorizontalRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x},SVGPathSegLinetoHorizontalRel.prototype.clone=function(){return new SVGPathSegLinetoHorizontalRel(void 0,this._x)},Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoVerticalAbs=function(a,b){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS,"V",a),this._y=b},SVGPathSegLinetoVerticalAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoVerticalAbs.prototype.toString=function(){return"[object SVGPathSegLinetoVerticalAbs]"},SVGPathSegLinetoVerticalAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._y},SVGPathSegLinetoVerticalAbs.prototype.clone=function(){return new SVGPathSegLinetoVerticalAbs(void 0,this._y)},Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoVerticalRel=function(a,b){ -SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL,"v",a),this._y=b},SVGPathSegLinetoVerticalRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoVerticalRel.prototype.toString=function(){return"[object SVGPathSegLinetoVerticalRel]"},SVGPathSegLinetoVerticalRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._y},SVGPathSegLinetoVerticalRel.prototype.clone=function(){return new SVGPathSegLinetoVerticalRel(void 0,this._y)},Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicSmoothAbs=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS,"S",a),this._x=b,this._y=c,this._x2=d,this._y2=e},SVGPathSegCurvetoCubicSmoothAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicSmoothAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicSmoothAbs]"},SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicSmoothAbs.prototype.clone=function(){return new SVGPathSegCurvetoCubicSmoothAbs(void 0,this._x,this._y,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicSmoothRel=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL,"s",a),this._x=b,this._y=c,this._x2=d,this._y2=e},SVGPathSegCurvetoCubicSmoothRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicSmoothRel.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicSmoothRel]"},SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicSmoothRel.prototype.clone=function(){return new SVGPathSegCurvetoCubicSmoothRel(void 0,this._x,this._y,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticSmoothAbs=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS,"T",a),this._x=b,this._y=c},SVGPathSegCurvetoQuadraticSmoothAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticSmoothAbs]"},SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticSmoothAbs(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticSmoothRel=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,"t",a),this._x=b,this._y=c},SVGPathSegCurvetoQuadraticSmoothRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticSmoothRel]"},SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticSmoothRel(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),SVGPathElement.prototype.createSVGPathSegClosePath=function(){return new SVGPathSegClosePath(void 0)},SVGPathElement.prototype.createSVGPathSegMovetoAbs=function(a,b){return new SVGPathSegMovetoAbs(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegMovetoRel=function(a,b){return new SVGPathSegMovetoRel(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegLinetoAbs=function(a,b){return new SVGPathSegLinetoAbs(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegLinetoRel=function(a,b){return new SVGPathSegLinetoRel(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs=function(a,b,c,d,e,f){return new SVGPathSegCurvetoCubicAbs(void 0,a,b,c,d,e,f)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel=function(a,b,c,d,e,f){return new SVGPathSegCurvetoCubicRel(void 0,a,b,c,d,e,f)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs=function(a,b,c,d){return new SVGPathSegCurvetoQuadraticAbs(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel=function(a,b,c,d){return new SVGPathSegCurvetoQuadraticRel(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegArcAbs=function(a,b,c,d,e,f,g){return new SVGPathSegArcAbs(void 0,a,b,c,d,e,f,g)},SVGPathElement.prototype.createSVGPathSegArcRel=function(a,b,c,d,e,f,g){return new SVGPathSegArcRel(void 0,a,b,c,d,e,f,g)},SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs=function(a){return new SVGPathSegLinetoHorizontalAbs(void 0,a)},SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel=function(a){return new SVGPathSegLinetoHorizontalRel(void 0,a)},SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs=function(a){return new SVGPathSegLinetoVerticalAbs(void 0,a)},SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel=function(a){return new SVGPathSegLinetoVerticalRel(void 0,a)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs=function(a,b,c,d){return new SVGPathSegCurvetoCubicSmoothAbs(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel=function(a,b,c,d){return new SVGPathSegCurvetoCubicSmoothRel(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs=function(a,b){return new SVGPathSegCurvetoQuadraticSmoothAbs(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel=function(a,b){return new SVGPathSegCurvetoQuadraticSmoothRel(void 0,a,b)}),"SVGPathSegList"in a||(a.SVGPathSegList=function(a){this._pathElement=a,this._list=this._parsePath(this._pathElement.getAttribute("d")),this._mutationObserverConfig={attributes:!0,attributeFilter:["d"]},this._pathElementMutationObserver=new MutationObserver(this._updateListFromPathMutations.bind(this)),this._pathElementMutationObserver.observe(this._pathElement,this._mutationObserverConfig)},Object.defineProperty(SVGPathSegList.prototype,"numberOfItems",{get:function(){return this._checkPathSynchronizedToList(),this._list.length},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"pathSegList",{get:function(){return this._pathSegList||(this._pathSegList=new SVGPathSegList(this)),this._pathSegList},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"normalizedPathSegList",{get:function(){return this.pathSegList},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"animatedPathSegList",{get:function(){return this.pathSegList},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"animatedNormalizedPathSegList",{get:function(){return this.pathSegList},enumerable:!0}),SVGPathSegList.prototype._checkPathSynchronizedToList=function(){this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords())},SVGPathSegList.prototype._updateListFromPathMutations=function(a){if(this._pathElement){var b=!1;a.forEach(function(a){"d"==a.attributeName&&(b=!0)}),b&&(this._list=this._parsePath(this._pathElement.getAttribute("d")))}},SVGPathSegList.prototype._writeListToPath=function(){this._pathElementMutationObserver.disconnect(),this._pathElement.setAttribute("d",SVGPathSegList._pathSegArrayAsString(this._list)),this._pathElementMutationObserver.observe(this._pathElement,this._mutationObserverConfig)},SVGPathSegList.prototype.segmentChanged=function(a){this._writeListToPath()},SVGPathSegList.prototype.clear=function(){this._checkPathSynchronizedToList(),this._list.forEach(function(a){a._owningPathSegList=null}),this._list=[],this._writeListToPath()},SVGPathSegList.prototype.initialize=function(a){return this._checkPathSynchronizedToList(),this._list=[a],a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList.prototype._checkValidIndex=function(a){if(isNaN(a)||0>a||a>=this.numberOfItems)throw"INDEX_SIZE_ERR"},SVGPathSegList.prototype.getItem=function(a){return this._checkPathSynchronizedToList(),this._checkValidIndex(a),this._list[a]},SVGPathSegList.prototype.insertItemBefore=function(a,b){return this._checkPathSynchronizedToList(),b>this.numberOfItems&&(b=this.numberOfItems),a._owningPathSegList&&(a=a.clone()),this._list.splice(b,0,a),a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList.prototype.replaceItem=function(a,b){return this._checkPathSynchronizedToList(),a._owningPathSegList&&(a=a.clone()),this._checkValidIndex(b),this._list[b]=a,a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList.prototype.removeItem=function(a){this._checkPathSynchronizedToList(),this._checkValidIndex(a);var b=this._list[a];return this._list.splice(a,1),this._writeListToPath(),b},SVGPathSegList.prototype.appendItem=function(a){return this._checkPathSynchronizedToList(),a._owningPathSegList&&(a=a.clone()),this._list.push(a),a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList._pathSegArrayAsString=function(a){var b="",c=!0;return a.forEach(function(a){c?(c=!1,b+=a._asPathString()):b+=" "+a._asPathString()}),b},SVGPathSegList.prototype._parsePath=function(a){if(!a||0==a.length)return[];var b=this,c=function(){this.pathSegList=[]};c.prototype.appendSegment=function(a){this.pathSegList.push(a)};var d=function(a){this._string=a,this._currentIndex=0,this._endIndex=this._string.length,this._previousCommand=SVGPathSeg.PATHSEG_UNKNOWN,this._skipOptionalSpaces()};d.prototype._isCurrentSpace=function(){var a=this._string[this._currentIndex];return" ">=a&&(" "==a||"\n"==a||" "==a||"\r"==a||"\f"==a)},d.prototype._skipOptionalSpaces=function(){for(;this._currentIndex="0"&&"9">=a)&&b!=SVGPathSeg.PATHSEG_CLOSEPATH?b==SVGPathSeg.PATHSEG_MOVETO_ABS?SVGPathSeg.PATHSEG_LINETO_ABS:b==SVGPathSeg.PATHSEG_MOVETO_REL?SVGPathSeg.PATHSEG_LINETO_REL:b:SVGPathSeg.PATHSEG_UNKNOWN},d.prototype.initialCommandIsMoveTo=function(){if(!this.hasMoreData())return!0;var a=this.peekSegmentType();return a==SVGPathSeg.PATHSEG_MOVETO_ABS||a==SVGPathSeg.PATHSEG_MOVETO_REL},d.prototype._parseNumber=function(){var a=0,b=0,c=1,d=0,e=1,f=1,g=this._currentIndex;if(this._skipOptionalSpaces(),this._currentIndex"9")&&"."!=this._string.charAt(this._currentIndex))){for(var h=this._currentIndex;this._currentIndex="0"&&this._string.charAt(this._currentIndex)<="9";)this._currentIndex++;if(this._currentIndex!=h)for(var i=this._currentIndex-1,j=1;i>=h;)b+=j*(this._string.charAt(i--)-"0"),j*=10;if(this._currentIndex=this._endIndex||this._string.charAt(this._currentIndex)<"0"||this._string.charAt(this._currentIndex)>"9")return;for(;this._currentIndex="0"&&this._string.charAt(this._currentIndex)<="9";)d+=(this._string.charAt(this._currentIndex++)-"0")*(c*=.1)}if(this._currentIndex!=g&&this._currentIndex+1=this._endIndex||this._string.charAt(this._currentIndex)<"0"||this._string.charAt(this._currentIndex)>"9")return;for(;this._currentIndex="0"&&this._string.charAt(this._currentIndex)<="9";)a*=10,a+=this._string.charAt(this._currentIndex)-"0",this._currentIndex++}var k=b+d;if(k*=e,a&&(k*=Math.pow(10,f*a)),g!=this._currentIndex)return this._skipOptionalSpacesOrDelimiter(),k}},d.prototype._parseArcFlag=function(){if(!(this._currentIndex>=this._endIndex)){var a=!1,b=this._string.charAt(this._currentIndex++);if("0"==b)a=!1;else{if("1"!=b)return;a=!0}return this._skipOptionalSpacesOrDelimiter(),a}},d.prototype.parseSegment=function(){var a=this._string[this._currentIndex],c=this._pathSegTypeFromChar(a);if(c==SVGPathSeg.PATHSEG_UNKNOWN){if(this._previousCommand==SVGPathSeg.PATHSEG_UNKNOWN)return null;if(c=this._nextCommandHelper(a,this._previousCommand),c==SVGPathSeg.PATHSEG_UNKNOWN)return null}else this._currentIndex++;switch(this._previousCommand=c,c){case SVGPathSeg.PATHSEG_MOVETO_REL:return new SVGPathSegMovetoRel(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_MOVETO_ABS:return new SVGPathSegMovetoAbs(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_REL:return new SVGPathSegLinetoRel(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_ABS:return new SVGPathSegLinetoAbs(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:return new SVGPathSegLinetoHorizontalRel(b,this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:return new SVGPathSegLinetoHorizontalAbs(b,this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:return new SVGPathSegLinetoVerticalRel(b,this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:return new SVGPathSegLinetoVerticalAbs(b,this._parseNumber());case SVGPathSeg.PATHSEG_CLOSEPATH:return this._skipOptionalSpaces(),new SVGPathSegClosePath(b);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:var d={x1:this._parseNumber(),y1:this._parseNumber(),x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicRel(b,d.x,d.y,d.x1,d.y1,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:var d={x1:this._parseNumber(),y1:this._parseNumber(),x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicAbs(b,d.x,d.y,d.x1,d.y1,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:var d={x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicSmoothRel(b,d.x,d.y,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:var d={x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicSmoothAbs(b,d.x,d.y,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:var d={x1:this._parseNumber(),y1:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoQuadraticRel(b,d.x,d.y,d.x1,d.y1);case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:var d={x1:this._parseNumber(),y1:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoQuadraticAbs(b,d.x,d.y,d.x1,d.y1);case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:return new SVGPathSegCurvetoQuadraticSmoothRel(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:return new SVGPathSegCurvetoQuadraticSmoothAbs(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_ARC_REL:var d={x1:this._parseNumber(),y1:this._parseNumber(),arcAngle:this._parseNumber(),arcLarge:this._parseArcFlag(),arcSweep:this._parseArcFlag(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegArcRel(b,d.x,d.y,d.x1,d.y1,d.arcAngle,d.arcLarge,d.arcSweep);case SVGPathSeg.PATHSEG_ARC_ABS:var d={x1:this._parseNumber(),y1:this._parseNumber(),arcAngle:this._parseNumber(),arcLarge:this._parseArcFlag(),arcSweep:this._parseArcFlag(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegArcAbs(b,d.x,d.y,d.x1,d.y1,d.arcAngle,d.arcLarge,d.arcSweep);default:throw"Unknown path seg type."}};var e=new c,f=new d(a);if(!f.initialCommandIsMoveTo())return[];for(;f.hasMoreData();){var g=f.parseSegment();if(!g)return[];e.appendSegment(g)}return e.pathSegList})}(),"function"==typeof define&&define.amd?define("c3",["d3"],function(){return k}):"undefined"!=typeof exports&&"undefined"!=typeof module?module.exports=k:a.c3=k}(window); \ No newline at end of file diff --git a/hal-core/resources/web/js/lib/d3.LICENSE b/hal-core/resources/web/js/lib/d3.LICENSE deleted file mode 100644 index b0145150..00000000 --- a/hal-core/resources/web/js/lib/d3.LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2010-2021 Mike Bostock - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. diff --git a/hal-core/resources/web/js/lib/d3.LICENSE.txt b/hal-core/resources/web/js/lib/d3.LICENSE.txt deleted file mode 100644 index b0145150..00000000 --- a/hal-core/resources/web/js/lib/d3.LICENSE.txt +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2010-2021 Mike Bostock - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. diff --git a/hal-core/resources/web/js/lib/d3.js b/hal-core/resources/web/js/lib/d3.js deleted file mode 100644 index aded45c4..00000000 --- a/hal-core/resources/web/js/lib/d3.js +++ /dev/null @@ -1,9554 +0,0 @@ -!function() { - var d3 = { - version: "3.5.17" - }; - var d3_arraySlice = [].slice, d3_array = function(list) { - return d3_arraySlice.call(list); - }; - var d3_document = this.document; - function d3_documentElement(node) { - return node && (node.ownerDocument || node.document || node).documentElement; - } - function d3_window(node) { - return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); - } - if (d3_document) { - try { - d3_array(d3_document.documentElement.childNodes)[0].nodeType; - } catch (e) { - d3_array = function(list) { - var i = list.length, array = new Array(i); - while (i--) array[i] = list[i]; - return array; - }; - } - } - if (!Date.now) Date.now = function() { - return +new Date(); - }; - if (d3_document) { - try { - d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); - } catch (error) { - var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; - d3_element_prototype.setAttribute = function(name, value) { - d3_element_setAttribute.call(this, name, value + ""); - }; - d3_element_prototype.setAttributeNS = function(space, local, value) { - d3_element_setAttributeNS.call(this, space, local, value + ""); - }; - d3_style_prototype.setProperty = function(name, value, priority) { - d3_style_setProperty.call(this, name, value + "", priority); - }; - } - } - d3.ascending = d3_ascending; - function d3_ascending(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; - } - d3.descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; - }; - d3.min = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; - } - return a; - }; - d3.max = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; - } - return a; - }; - d3.extent = function(array, f) { - var i = -1, n = array.length, a, b, c; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } - return [ a, c ]; - }; - function d3_number(x) { - return x === null ? NaN : +x; - } - function d3_numeric(x) { - return !isNaN(x); - } - d3.sum = function(array, f) { - var s = 0, n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = +array[i])) s += a; - } else { - while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; - } - return s; - }; - d3.mean = function(array, f) { - var s = 0, n = array.length, a, i = -1, j = n; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; - } - if (j) return s / j; - }; - d3.quantile = function(values, p) { - var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; - return e ? v + e * (values[h] - v) : v; - }; - d3.median = function(array, f) { - var numbers = [], n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); - } - if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); - }; - d3.variance = function(array, f) { - var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; - if (arguments.length === 1) { - while (++i < n) { - if (d3_numeric(a = d3_number(array[i]))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } else { - while (++i < n) { - if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } - if (j > 1) return s / (j - 1); - }; - d3.deviation = function() { - var v = d3.variance.apply(this, arguments); - return v ? Math.sqrt(v) : v; - }; - function d3_bisector(compare) { - return { - left: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; - } - return lo; - } - }; - } - var d3_bisect = d3_bisector(d3_ascending); - d3.bisectLeft = d3_bisect.left; - d3.bisect = d3.bisectRight = d3_bisect.right; - d3.bisector = function(f) { - return d3_bisector(f.length === 1 ? function(d, x) { - return d3_ascending(f(d), x); - } : f); - }; - d3.shuffle = function(array, i0, i1) { - if ((m = arguments.length) < 3) { - i1 = array.length; - if (m < 2) i0 = 0; - } - var m = i1 - i0, t, i; - while (m) { - i = Math.random() * m-- | 0; - t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; - } - return array; - }; - d3.permute = function(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; - }; - d3.pairs = function(array) { - var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; - return pairs; - }; - d3.transpose = function(matrix) { - if (!(n = matrix.length)) return []; - for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) { - for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) { - row[j] = matrix[j][i]; - } - } - return transpose; - }; - function d3_transposeLength(d) { - return d.length; - } - d3.zip = function() { - return d3.transpose(arguments); - }; - d3.keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; - }; - d3.values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; - }; - d3.entries = function(map) { - var entries = []; - for (var key in map) entries.push({ - key: key, - value: map[key] - }); - return entries; - }; - d3.merge = function(arrays) { - var n = arrays.length, m, i = -1, j = 0, merged, array; - while (++i < n) j += arrays[i].length; - merged = new Array(j); - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - return merged; - }; - var abs = Math.abs; - d3.range = function(start, stop, step) { - if (arguments.length < 3) { - step = 1; - if (arguments.length < 2) { - stop = start; - start = 0; - } - } - if ((stop - start) / step === Infinity) throw new Error("infinite range"); - var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; - start *= k, stop *= k, step *= k; - if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); - return range; - }; - function d3_range_integerScale(x) { - var k = 1; - while (x * k % 1) k *= 10; - return k; - } - function d3_class(ctor, properties) { - for (var key in properties) { - Object.defineProperty(ctor.prototype, key, { - value: properties[key], - enumerable: false - }); - } - } - d3.map = function(object, f) { - var map = new d3_Map(); - if (object instanceof d3_Map) { - object.forEach(function(key, value) { - map.set(key, value); - }); - } else if (Array.isArray(object)) { - var i = -1, n = object.length, o; - if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); - } else { - for (var key in object) map.set(key, object[key]); - } - return map; - }; - function d3_Map() { - this._ = Object.create(null); - } - var d3_map_proto = "__proto__", d3_map_zero = "\x00"; - d3_class(d3_Map, { - has: d3_map_has, - get: function(key) { - return this._[d3_map_escape(key)]; - }, - set: function(key, value) { - return this._[d3_map_escape(key)] = value; - }, - remove: d3_map_remove, - keys: d3_map_keys, - values: function() { - var values = []; - for (var key in this._) values.push(this._[key]); - return values; - }, - entries: function() { - var entries = []; - for (var key in this._) entries.push({ - key: d3_map_unescape(key), - value: this._[key] - }); - return entries; - }, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); - } - }); - function d3_map_escape(key) { - return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; - } - function d3_map_unescape(key) { - return (key += "")[0] === d3_map_zero ? key.slice(1) : key; - } - function d3_map_has(key) { - return d3_map_escape(key) in this._; - } - function d3_map_remove(key) { - return (key = d3_map_escape(key)) in this._ && delete this._[key]; - } - function d3_map_keys() { - var keys = []; - for (var key in this._) keys.push(d3_map_unescape(key)); - return keys; - } - function d3_map_size() { - var size = 0; - for (var key in this._) ++size; - return size; - } - function d3_map_empty() { - for (var key in this._) return false; - return true; - } - d3.nest = function() { - var nest = {}, keys = [], sortKeys = [], sortValues, rollup; - function map(mapType, array, depth) { - if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; - var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(object = array[i]))) { - values.push(object); - } else { - valuesByKey.set(keyValue, [ object ]); - } - } - if (mapType) { - object = mapType(); - setter = function(keyValue, values) { - object.set(keyValue, map(mapType, values, depth)); - }; - } else { - object = {}; - setter = function(keyValue, values) { - object[keyValue] = map(mapType, values, depth); - }; - } - valuesByKey.forEach(setter); - return object; - } - function entries(map, depth) { - if (depth >= keys.length) return map; - var array = [], sortKey = sortKeys[depth++]; - map.forEach(function(key, keyMap) { - array.push({ - key: key, - values: entries(keyMap, depth) - }); - }); - return sortKey ? array.sort(function(a, b) { - return sortKey(a.key, b.key); - }) : array; - } - nest.map = function(array, mapType) { - return map(mapType, array, 0); - }; - nest.entries = function(array) { - return entries(map(d3.map, array, 0), 0); - }; - nest.key = function(d) { - keys.push(d); - return nest; - }; - nest.sortKeys = function(order) { - sortKeys[keys.length - 1] = order; - return nest; - }; - nest.sortValues = function(order) { - sortValues = order; - return nest; - }; - nest.rollup = function(f) { - rollup = f; - return nest; - }; - return nest; - }; - d3.set = function(array) { - var set = new d3_Set(); - if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); - return set; - }; - function d3_Set() { - this._ = Object.create(null); - } - d3_class(d3_Set, { - has: d3_map_has, - add: function(key) { - this._[d3_map_escape(key += "")] = true; - return key; - }, - remove: d3_map_remove, - values: d3_map_keys, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key)); - } - }); - d3.behavior = {}; - function d3_identity(d) { - return d; - } - d3.rebind = function(target, source) { - var i = 1, n = arguments.length, method; - while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); - return target; - }; - function d3_rebind(target, source, method) { - return function() { - var value = method.apply(source, arguments); - return value === source ? target : value; - }; - } - function d3_vendorSymbol(object, name) { - if (name in object) return name; - name = name.charAt(0).toUpperCase() + name.slice(1); - for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { - var prefixName = d3_vendorPrefixes[i] + name; - if (prefixName in object) return prefixName; - } - } - var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; - function d3_noop() {} - d3.dispatch = function() { - var dispatch = new d3_dispatch(), i = -1, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - return dispatch; - }; - function d3_dispatch() {} - d3_dispatch.prototype.on = function(type, listener) { - var i = type.indexOf("."), name = ""; - if (i >= 0) { - name = type.slice(i + 1); - type = type.slice(0, i); - } - if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); - if (arguments.length === 2) { - if (listener == null) for (type in this) { - if (this.hasOwnProperty(type)) this[type].on(name, null); - } - return this; - } - }; - function d3_dispatch_event(dispatch) { - var listeners = [], listenerByName = new d3_Map(); - function event() { - var z = listeners, i = -1, n = z.length, l; - while (++i < n) if (l = z[i].on) l.apply(this, arguments); - return dispatch; - } - event.on = function(name, listener) { - var l = listenerByName.get(name), i; - if (arguments.length < 2) return l && l.on; - if (l) { - l.on = null; - listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); - listenerByName.remove(name); - } - if (listener) listeners.push(listenerByName.set(name, { - on: listener - })); - return dispatch; - }; - return event; - } - d3.event = null; - function d3_eventPreventDefault() { - d3.event.preventDefault(); - } - function d3_eventSource() { - var e = d3.event, s; - while (s = e.sourceEvent) e = s; - return e; - } - function d3_eventDispatch(target) { - var dispatch = new d3_dispatch(), i = 0, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - dispatch.of = function(thiz, argumentz) { - return function(e1) { - try { - var e0 = e1.sourceEvent = d3.event; - e1.target = target; - d3.event = e1; - dispatch[e1.type].apply(thiz, argumentz); - } finally { - d3.event = e0; - } - }; - }; - return dispatch; - } - d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); - }; - var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - var d3_subclass = {}.__proto__ ? function(object, prototype) { - object.__proto__ = prototype; - } : function(object, prototype) { - for (var property in prototype) object[property] = prototype[property]; - }; - function d3_selection(groups) { - d3_subclass(groups, d3_selectionPrototype); - return groups; - } - var d3_select = function(s, n) { - return n.querySelector(s); - }, d3_selectAll = function(s, n) { - return n.querySelectorAll(s); - }, d3_selectMatches = function(n, s) { - var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; - d3_selectMatches = function(n, s) { - return d3_selectMatcher.call(n, s); - }; - return d3_selectMatches(n, s); - }; - if (typeof Sizzle === "function") { - d3_select = function(s, n) { - return Sizzle(s, n)[0] || null; - }; - d3_selectAll = Sizzle; - d3_selectMatches = Sizzle.matchesSelector; - } - d3.selection = function() { - return d3.select(d3_document.documentElement); - }; - var d3_selectionPrototype = d3.selection.prototype = []; - d3_selectionPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, group, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(subnode = selector.call(node, node.__data__, i, j)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selector(selector) { - return typeof selector === "function" ? selector : function() { - return d3_select(selector, this); - }; - } - d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], subgroup, node; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); - subgroup.parentNode = node; - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selectorAll(selector) { - return typeof selector === "function" ? selector : function() { - return d3_selectAll(selector, this); - }; - } - var d3_nsXhtml = "http://www.w3.org/1999/xhtml"; - var d3_nsPrefix = { - svg: "http://www.w3.org/2000/svg", - xhtml: d3_nsXhtml, - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - d3.ns = { - prefix: d3_nsPrefix, - qualify: function(name) { - var i = name.indexOf(":"), prefix = name; - if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); - return d3_nsPrefix.hasOwnProperty(prefix) ? { - space: d3_nsPrefix[prefix], - local: name - } : name; - } - }; - d3_selectionPrototype.attr = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(); - name = d3.ns.qualify(name); - return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); - } - for (value in name) this.each(d3_selection_attr(value, name[value])); - return this; - } - return this.each(d3_selection_attr(name, value)); - }; - function d3_selection_attr(name, value) { - name = d3.ns.qualify(name); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrConstant() { - this.setAttribute(name, value); - } - function attrConstantNS() { - this.setAttributeNS(name.space, name.local, value); - } - function attrFunction() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); - } - function attrFunctionNS() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); - } - return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; - } - function d3_collapse(s) { - return s.trim().replace(/\s+/g, " "); - } - d3_selectionPrototype.classed = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; - if (value = node.classList) { - while (++i < n) if (!value.contains(name[i])) return false; - } else { - value = node.getAttribute("class"); - while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; - } - return true; - } - for (value in name) this.each(d3_selection_classed(value, name[value])); - return this; - } - return this.each(d3_selection_classed(name, value)); - }; - function d3_selection_classedRe(name) { - return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); - } - function d3_selection_classes(name) { - return (name + "").trim().split(/^|\s+/); - } - function d3_selection_classed(name, value) { - name = d3_selection_classes(name).map(d3_selection_classedName); - var n = name.length; - function classedConstant() { - var i = -1; - while (++i < n) name[i](this, value); - } - function classedFunction() { - var i = -1, x = value.apply(this, arguments); - while (++i < n) name[i](this, x); - } - return typeof value === "function" ? classedFunction : classedConstant; - } - function d3_selection_classedName(name) { - var re = d3_selection_classedRe(name); - return function(node, value) { - if (c = node.classList) return value ? c.add(name) : c.remove(name); - var c = node.getAttribute("class") || ""; - if (value) { - re.lastIndex = 0; - if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); - } else { - node.setAttribute("class", d3_collapse(c.replace(re, " "))); - } - }; - } - d3_selectionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); - return this; - } - if (n < 2) { - var node = this.node(); - return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); - } - priority = ""; - } - return this.each(d3_selection_style(name, value, priority)); - }; - function d3_selection_style(name, value, priority) { - function styleNull() { - this.style.removeProperty(name); - } - function styleConstant() { - this.style.setProperty(name, value, priority); - } - function styleFunction() { - var x = value.apply(this, arguments); - if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); - } - return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; - } - d3_selectionPrototype.property = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") return this.node()[name]; - for (value in name) this.each(d3_selection_property(value, name[value])); - return this; - } - return this.each(d3_selection_property(name, value)); - }; - function d3_selection_property(name, value) { - function propertyNull() { - delete this[name]; - } - function propertyConstant() { - this[name] = value; - } - function propertyFunction() { - var x = value.apply(this, arguments); - if (x == null) delete this[name]; else this[name] = x; - } - return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; - } - d3_selectionPrototype.text = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - } : value == null ? function() { - this.textContent = ""; - } : function() { - this.textContent = value; - }) : this.node().textContent; - }; - d3_selectionPrototype.html = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - } : value == null ? function() { - this.innerHTML = ""; - } : function() { - this.innerHTML = value; - }) : this.node().innerHTML; - }; - d3_selectionPrototype.append = function(name) { - name = d3_selection_creator(name); - return this.select(function() { - return this.appendChild(name.apply(this, arguments)); - }); - }; - function d3_selection_creator(name) { - function create() { - var document = this.ownerDocument, namespace = this.namespaceURI; - return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name); - } - function createNS() { - return this.ownerDocument.createElementNS(name.space, name.local); - } - return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; - } - d3_selectionPrototype.insert = function(name, before) { - name = d3_selection_creator(name); - before = d3_selection_selector(before); - return this.select(function() { - return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); - }); - }; - d3_selectionPrototype.remove = function() { - return this.each(d3_selectionRemove); - }; - function d3_selectionRemove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - } - d3_selectionPrototype.data = function(value, key) { - var i = -1, n = this.length, group, node; - if (!arguments.length) { - value = new Array(n = (group = this[0]).length); - while (++i < n) { - if (node = group[i]) { - value[i] = node.__data__; - } - } - return value; - } - function bind(group, groupData) { - var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; - if (key) { - var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; - for (i = -1; ++i < n; ) { - if (node = group[i]) { - if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { - exitNodes[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - keyValues[i] = keyValue; - } - } - for (i = -1; ++i < m; ) { - if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { - enterNodes[i] = d3_selection_dataNode(nodeData); - } else if (node !== true) { - updateNodes[i] = node; - node.__data__ = nodeData; - } - nodeByKeyValue.set(keyValue, true); - } - for (i = -1; ++i < n; ) { - if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { - exitNodes[i] = group[i]; - } - } - } else { - for (i = -1; ++i < n0; ) { - node = group[i]; - nodeData = groupData[i]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - } - for (;i < m; ++i) { - enterNodes[i] = d3_selection_dataNode(groupData[i]); - } - for (;i < n; ++i) { - exitNodes[i] = group[i]; - } - } - enterNodes.update = updateNodes; - enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; - enter.push(enterNodes); - update.push(updateNodes); - exit.push(exitNodes); - } - var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); - if (typeof value === "function") { - while (++i < n) { - bind(group = this[i], value.call(group, group.parentNode.__data__, i)); - } - } else { - while (++i < n) { - bind(group = this[i], value); - } - } - update.enter = function() { - return enter; - }; - update.exit = function() { - return exit; - }; - return update; - }; - function d3_selection_dataNode(data) { - return { - __data__: data - }; - } - d3_selectionPrototype.datum = function(value) { - return arguments.length ? this.property("__data__", value) : this.property("__data__"); - }; - d3_selectionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_filter(selector) { - return function() { - return d3_selectMatches(this, selector); - }; - } - d3_selectionPrototype.order = function() { - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - return this; - }; - d3_selectionPrototype.sort = function(comparator) { - comparator = d3_selection_sortComparator.apply(this, arguments); - for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); - return this.order(); - }; - function d3_selection_sortComparator(comparator) { - if (!arguments.length) comparator = d3_ascending; - return function(a, b) { - return a && b ? comparator(a.__data__, b.__data__) : !a - !b; - }; - } - d3_selectionPrototype.each = function(callback) { - return d3_selection_each(this, function(node, i, j) { - callback.call(node, node.__data__, i, j); - }); - }; - function d3_selection_each(groups, callback) { - for (var j = 0, m = groups.length; j < m; j++) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { - if (node = group[i]) callback(node, i, j); - } - } - return groups; - } - d3_selectionPrototype.call = function(callback) { - var args = d3_array(arguments); - callback.apply(args[0] = this, args); - return this; - }; - d3_selectionPrototype.empty = function() { - return !this.node(); - }; - d3_selectionPrototype.node = function() { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) return node; - } - } - return null; - }; - d3_selectionPrototype.size = function() { - var n = 0; - d3_selection_each(this, function() { - ++n; - }); - return n; - }; - function d3_selection_enter(selection) { - d3_subclass(selection, d3_selection_enterPrototype); - return selection; - } - var d3_selection_enterPrototype = []; - d3.selection.enter = d3_selection_enter; - d3.selection.enter.prototype = d3_selection_enterPrototype; - d3_selection_enterPrototype.append = d3_selectionPrototype.append; - d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; - d3_selection_enterPrototype.node = d3_selectionPrototype.node; - d3_selection_enterPrototype.call = d3_selectionPrototype.call; - d3_selection_enterPrototype.size = d3_selectionPrototype.size; - d3_selection_enterPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, upgroup, group, node; - for (var j = -1, m = this.length; ++j < m; ) { - upgroup = (group = this[j]).update; - subgroups.push(subgroup = []); - subgroup.parentNode = group.parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - d3_selection_enterPrototype.insert = function(name, before) { - if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); - return d3_selectionPrototype.insert.call(this, name, before); - }; - function d3_selection_enterInsertBefore(enter) { - var i0, j0; - return function(d, i, j) { - var group = enter[j].update, n = group.length, node; - if (j != j0) j0 = j, i0 = 0; - if (i >= i0) i0 = i + 1; - while (!(node = group[i0]) && ++i0 < n) ; - return node; - }; - } - d3.select = function(node) { - var group; - if (typeof node === "string") { - group = [ d3_select(node, d3_document) ]; - group.parentNode = d3_document.documentElement; - } else { - group = [ node ]; - group.parentNode = d3_documentElement(node); - } - return d3_selection([ group ]); - }; - d3.selectAll = function(nodes) { - var group; - if (typeof nodes === "string") { - group = d3_array(d3_selectAll(nodes, d3_document)); - group.parentNode = d3_document.documentElement; - } else { - group = d3_array(nodes); - group.parentNode = null; - } - return d3_selection([ group ]); - }; - d3_selectionPrototype.on = function(type, listener, capture) { - var n = arguments.length; - if (n < 3) { - if (typeof type !== "string") { - if (n < 2) listener = false; - for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); - return this; - } - if (n < 2) return (n = this.node()["__on" + type]) && n._; - capture = false; - } - return this.each(d3_selection_on(type, listener, capture)); - }; - function d3_selection_on(type, listener, capture) { - var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; - if (i > 0) type = type.slice(0, i); - var filter = d3_selection_onFilters.get(type); - if (filter) type = filter, wrap = d3_selection_onFilter; - function onRemove() { - var l = this[name]; - if (l) { - this.removeEventListener(type, l, l.$); - delete this[name]; - } - } - function onAdd() { - var l = wrap(listener, d3_array(arguments)); - onRemove.call(this); - this.addEventListener(type, this[name] = l, l.$ = capture); - l._ = listener; - } - function removeAll() { - var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; - for (var name in this) { - if (match = name.match(re)) { - var l = this[name]; - this.removeEventListener(match[1], l, l.$); - delete this[name]; - } - } - } - return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; - } - var d3_selection_onFilters = d3.map({ - mouseenter: "mouseover", - mouseleave: "mouseout" - }); - if (d3_document) { - d3_selection_onFilters.forEach(function(k) { - if ("on" + k in d3_document) d3_selection_onFilters.remove(k); - }); - } - function d3_selection_onListener(listener, argumentz) { - return function(e) { - var o = d3.event; - d3.event = e; - argumentz[0] = this.__data__; - try { - listener.apply(this, argumentz); - } finally { - d3.event = o; - } - }; - } - function d3_selection_onFilter(listener, argumentz) { - var l = d3_selection_onListener(listener, argumentz); - return function(e) { - var target = this, related = e.relatedTarget; - if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { - l.call(target, e); - } - }; - } - var d3_event_dragSelect, d3_event_dragId = 0; - function d3_event_dragSuppress(node) { - var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); - if (d3_event_dragSelect == null) { - d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); - } - if (d3_event_dragSelect) { - var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; - style[d3_event_dragSelect] = "none"; - } - return function(suppressClick) { - w.on(name, null); - if (d3_event_dragSelect) style[d3_event_dragSelect] = select; - if (suppressClick) { - var off = function() { - w.on(click, null); - }; - w.on(click, function() { - d3_eventPreventDefault(); - off(); - }, true); - setTimeout(off, 0); - } - }; - } - d3.mouse = function(container) { - return d3_mousePoint(container, d3_eventSource()); - }; - var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; - function d3_mousePoint(container, e) { - if (e.changedTouches) e = e.changedTouches[0]; - var svg = container.ownerSVGElement || container; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - if (d3_mouse_bug44083 < 0) { - var window = d3_window(container); - if (window.scrollX || window.scrollY) { - svg = d3.select("body").append("svg").style({ - position: "absolute", - top: 0, - left: 0, - margin: 0, - padding: 0, - border: "none" - }, "important"); - var ctm = svg[0][0].getScreenCTM(); - d3_mouse_bug44083 = !(ctm.f || ctm.e); - svg.remove(); - } - } - if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, - point.y = e.clientY; - point = point.matrixTransform(container.getScreenCTM().inverse()); - return [ point.x, point.y ]; - } - var rect = container.getBoundingClientRect(); - return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; - } - d3.touch = function(container, touches, identifier) { - if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; - if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { - if ((touch = touches[i]).identifier === identifier) { - return d3_mousePoint(container, touch); - } - } - }; - d3.behavior.drag = function() { - var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); - function drag() { - this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); - } - function dragstart(id, position, subject, move, end) { - return function() { - var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); - if (origin) { - dragOffset = origin.apply(that, arguments); - dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; - } else { - dragOffset = [ 0, 0 ]; - } - dispatch({ - type: "dragstart" - }); - function moved() { - var position1 = position(parent, dragId), dx, dy; - if (!position1) return; - dx = position1[0] - position0[0]; - dy = position1[1] - position0[1]; - dragged |= dx | dy; - position0 = position1; - dispatch({ - type: "drag", - x: position1[0] + dragOffset[0], - y: position1[1] + dragOffset[1], - dx: dx, - dy: dy - }); - } - function ended() { - if (!position(parent, dragId)) return; - dragSubject.on(move + dragName, null).on(end + dragName, null); - dragRestore(dragged); - dispatch({ - type: "dragend" - }); - } - }; - } - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - return d3.rebind(drag, event, "on"); - }; - function d3_behavior_dragTouchId() { - return d3.event.changedTouches[0].identifier; - } - d3.touches = function(container, touches) { - if (arguments.length < 2) touches = d3_eventSource().touches; - return touches ? d3_array(touches).map(function(touch) { - var point = d3_mousePoint(container, touch); - point.identifier = touch.identifier; - return point; - }) : []; - }; - var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; - function d3_sgn(x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } - function d3_cross2d(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); - } - function d3_acos(x) { - return x > 1 ? 0 : x < -1 ? π : Math.acos(x); - } - function d3_asin(x) { - return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); - } - function d3_sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; - } - function d3_cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; - } - function d3_tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); - } - function d3_haversin(x) { - return (x = Math.sin(x / 2)) * x; - } - var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; - d3.interpolateZoom = function(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; - if (d2 < ε2) { - S = Math.log(w1 / w0) / ρ; - i = function(t) { - return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; - }; - } else { - var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); - S = (r1 - r0) / ρ; - i = function(t) { - var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); - return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; - }; - } - i.duration = S * 1e3; - return i; - }; - d3.behavior.zoom = function() { - var view = { - x: 0, - y: 0, - k: 1 - }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; - if (!d3_behavior_zoomWheel) { - d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); - }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return d3.event.wheelDelta; - }, "mousewheel") : (d3_behavior_zoomDelta = function() { - return -d3.event.detail; - }, "MozMousePixelScroll"); - } - function zoom(g) { - g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); - } - zoom.event = function(g) { - g.each(function() { - var dispatch = event.of(this, arguments), view1 = view; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.zoom", function() { - view = this.__chart__ || { - x: 0, - y: 0, - k: 1 - }; - zoomstarted(dispatch); - }).tween("zoom:zoom", function() { - var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); - return function(t) { - var l = i(t), k = dx / l[2]; - this.__chart__ = view = { - x: cx - l[0] * k, - y: cy - l[1] * k, - k: k - }; - zoomed(dispatch); - }; - }).each("interrupt.zoom", function() { - zoomended(dispatch); - }).each("end.zoom", function() { - zoomended(dispatch); - }); - } else { - this.__chart__ = view; - zoomstarted(dispatch); - zoomed(dispatch); - zoomended(dispatch); - } - }); - }; - zoom.translate = function(_) { - if (!arguments.length) return [ view.x, view.y ]; - view = { - x: +_[0], - y: +_[1], - k: view.k - }; - rescale(); - return zoom; - }; - zoom.scale = function(_) { - if (!arguments.length) return view.k; - view = { - x: view.x, - y: view.y, - k: null - }; - scaleTo(+_); - rescale(); - return zoom; - }; - zoom.scaleExtent = function(_) { - if (!arguments.length) return scaleExtent; - scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; - return zoom; - }; - zoom.center = function(_) { - if (!arguments.length) return center; - center = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.size = function(_) { - if (!arguments.length) return size; - size = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.duration = function(_) { - if (!arguments.length) return duration; - duration = +_; - return zoom; - }; - zoom.x = function(z) { - if (!arguments.length) return x1; - x1 = z; - x0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - zoom.y = function(z) { - if (!arguments.length) return y1; - y1 = z; - y0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - function location(p) { - return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; - } - function point(l) { - return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; - } - function scaleTo(s) { - view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); - } - function translateTo(p, l) { - l = point(l); - view.x += p[0] - l[0]; - view.y += p[1] - l[1]; - } - function zoomTo(that, p, l, k) { - that.__chart__ = { - x: view.x, - y: view.y, - k: view.k - }; - scaleTo(Math.pow(2, k)); - translateTo(center0 = p, l); - that = d3.select(that); - if (duration > 0) that = that.transition().duration(duration); - that.call(zoom.event); - } - function rescale() { - if (x1) x1.domain(x0.range().map(function(x) { - return (x - view.x) / view.k; - }).map(x0.invert)); - if (y1) y1.domain(y0.range().map(function(y) { - return (y - view.y) / view.k; - }).map(y0.invert)); - } - function zoomstarted(dispatch) { - if (!zooming++) dispatch({ - type: "zoomstart" - }); - } - function zoomed(dispatch) { - rescale(); - dispatch({ - type: "zoom", - scale: view.k, - translate: [ view.x, view.y ] - }); - } - function zoomended(dispatch) { - if (!--zooming) dispatch({ - type: "zoomend" - }), center0 = null; - } - function mousedowned() { - var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); - d3_selection_interrupt.call(that); - zoomstarted(dispatch); - function moved() { - dragged = 1; - translateTo(d3.mouse(that), location0); - zoomed(dispatch); - } - function ended() { - subject.on(mousemove, null).on(mouseup, null); - dragRestore(dragged); - zoomended(dispatch); - } - } - function touchstarted() { - var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); - started(); - zoomstarted(dispatch); - subject.on(mousedown, null).on(touchstart, started); - function relocate() { - var touches = d3.touches(that); - scale0 = view.k; - touches.forEach(function(t) { - if (t.identifier in locations0) locations0[t.identifier] = location(t); - }); - return touches; - } - function started() { - var target = d3.event.target; - d3.select(target).on(touchmove, moved).on(touchend, ended); - targets.push(target); - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - locations0[changed[i].identifier] = null; - } - var touches = relocate(), now = Date.now(); - if (touches.length === 1) { - if (now - touchtime < 500) { - var p = touches[0]; - zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); - d3_eventPreventDefault(); - } - touchtime = now; - } else if (touches.length > 1) { - var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; - distance0 = dx * dx + dy * dy; - } - } - function moved() { - var touches = d3.touches(that), p0, l0, p1, l1; - d3_selection_interrupt.call(that); - for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { - p1 = touches[i]; - if (l1 = locations0[p1.identifier]) { - if (l0) break; - p0 = p1, l0 = l1; - } - } - if (l1) { - var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); - p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; - l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; - scaleTo(scale1 * scale0); - } - touchtime = null; - translateTo(p0, l0); - zoomed(dispatch); - } - function ended() { - if (d3.event.touches.length) { - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - delete locations0[changed[i].identifier]; - } - for (var identifier in locations0) { - return void relocate(); - } - } - d3.selectAll(targets).on(zoomName, null); - subject.on(mousedown, mousedowned).on(touchstart, touchstarted); - dragRestore(); - zoomended(dispatch); - } - } - function mousewheeled() { - var dispatch = event.of(this, arguments); - if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), - translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); - mousewheelTimer = setTimeout(function() { - mousewheelTimer = null; - zoomended(dispatch); - }, 50); - d3_eventPreventDefault(); - scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); - translateTo(center0, translate0); - zoomed(dispatch); - } - function dblclicked() { - var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; - zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); - } - return d3.rebind(zoom, event, "on"); - }; - var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; - d3.color = d3_color; - function d3_color() {} - d3_color.prototype.toString = function() { - return this.rgb() + ""; - }; - d3.hsl = d3_hsl; - function d3_hsl(h, s, l) { - return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); - } - var d3_hslPrototype = d3_hsl.prototype = new d3_color(); - d3_hslPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, this.l / k); - }; - d3_hslPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, k * this.l); - }; - d3_hslPrototype.rgb = function() { - return d3_hsl_rgb(this.h, this.s, this.l); - }; - function d3_hsl_rgb(h, s, l) { - var m1, m2; - h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; - s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - m2 = l <= .5 ? l * (1 + s) : l + s - l * s; - m1 = 2 * l - m2; - function v(h) { - if (h > 360) h -= 360; else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; - } - function vv(h) { - return Math.round(v(h) * 255); - } - return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); - } - d3.hcl = d3_hcl; - function d3_hcl(h, c, l) { - return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); - } - var d3_hclPrototype = d3_hcl.prototype = new d3_color(); - d3_hclPrototype.brighter = function(k) { - return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.darker = function(k) { - return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.rgb = function() { - return d3_hcl_lab(this.h, this.c, this.l).rgb(); - }; - function d3_hcl_lab(h, c, l) { - if (isNaN(h)) h = 0; - if (isNaN(c)) c = 0; - return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); - } - d3.lab = d3_lab; - function d3_lab(l, a, b) { - return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); - } - var d3_lab_K = 18; - var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; - var d3_labPrototype = d3_lab.prototype = new d3_color(); - d3_labPrototype.brighter = function(k) { - return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.darker = function(k) { - return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.rgb = function() { - return d3_lab_rgb(this.l, this.a, this.b); - }; - function d3_lab_rgb(l, a, b) { - var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; - x = d3_lab_xyz(x) * d3_lab_X; - y = d3_lab_xyz(y) * d3_lab_Y; - z = d3_lab_xyz(z) * d3_lab_Z; - return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); - } - function d3_lab_hcl(l, a, b) { - return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); - } - function d3_lab_xyz(x) { - return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; - } - function d3_xyz_lab(x) { - return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; - } - function d3_xyz_rgb(r) { - return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); - } - d3.rgb = d3_rgb; - function d3_rgb(r, g, b) { - return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); - } - function d3_rgbNumber(value) { - return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); - } - function d3_rgbString(value) { - return d3_rgbNumber(value) + ""; - } - var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); - d3_rgbPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - var r = this.r, g = this.g, b = this.b, i = 30; - if (!r && !g && !b) return new d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); - }; - d3_rgbPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_rgb(k * this.r, k * this.g, k * this.b); - }; - d3_rgbPrototype.hsl = function() { - return d3_rgb_hsl(this.r, this.g, this.b); - }; - d3_rgbPrototype.toString = function() { - return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); - }; - function d3_rgb_hex(v) { - return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); - } - function d3_rgb_parse(format, rgb, hsl) { - var r = 0, g = 0, b = 0, m1, m2, color; - m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); - if (m1) { - m2 = m1[2].split(","); - switch (m1[1]) { - case "hsl": - { - return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); - } - - case "rgb": - { - return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); - } - } - } - if (color = d3_rgb_names.get(format)) { - return rgb(color.r, color.g, color.b); - } - if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { - if (format.length === 4) { - r = (color & 3840) >> 4; - r = r >> 4 | r; - g = color & 240; - g = g >> 4 | g; - b = color & 15; - b = b << 4 | b; - } else if (format.length === 7) { - r = (color & 16711680) >> 16; - g = (color & 65280) >> 8; - b = color & 255; - } - } - return rgb(r, g, b); - } - function d3_rgb_hsl(r, g, b) { - var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; - if (d) { - s = l < .5 ? d / (max + min) : d / (2 - max - min); - if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; - h *= 60; - } else { - h = NaN; - s = l > 0 && l < 1 ? 0 : h; - } - return new d3_hsl(h, s, l); - } - function d3_rgb_lab(r, g, b) { - r = d3_rgb_xyz(r); - g = d3_rgb_xyz(g); - b = d3_rgb_xyz(b); - var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); - return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); - } - function d3_rgb_xyz(r) { - return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); - } - function d3_rgb_parseNumber(c) { - var f = parseFloat(c); - return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; - } - var d3_rgb_names = d3.map({ - aliceblue: 15792383, - antiquewhite: 16444375, - aqua: 65535, - aquamarine: 8388564, - azure: 15794175, - beige: 16119260, - bisque: 16770244, - black: 0, - blanchedalmond: 16772045, - blue: 255, - blueviolet: 9055202, - brown: 10824234, - burlywood: 14596231, - cadetblue: 6266528, - chartreuse: 8388352, - chocolate: 13789470, - coral: 16744272, - cornflowerblue: 6591981, - cornsilk: 16775388, - crimson: 14423100, - cyan: 65535, - darkblue: 139, - darkcyan: 35723, - darkgoldenrod: 12092939, - darkgray: 11119017, - darkgreen: 25600, - darkgrey: 11119017, - darkkhaki: 12433259, - darkmagenta: 9109643, - darkolivegreen: 5597999, - darkorange: 16747520, - darkorchid: 10040012, - darkred: 9109504, - darksalmon: 15308410, - darkseagreen: 9419919, - darkslateblue: 4734347, - darkslategray: 3100495, - darkslategrey: 3100495, - darkturquoise: 52945, - darkviolet: 9699539, - deeppink: 16716947, - deepskyblue: 49151, - dimgray: 6908265, - dimgrey: 6908265, - dodgerblue: 2003199, - firebrick: 11674146, - floralwhite: 16775920, - forestgreen: 2263842, - fuchsia: 16711935, - gainsboro: 14474460, - ghostwhite: 16316671, - gold: 16766720, - goldenrod: 14329120, - gray: 8421504, - green: 32768, - greenyellow: 11403055, - grey: 8421504, - honeydew: 15794160, - hotpink: 16738740, - indianred: 13458524, - indigo: 4915330, - ivory: 16777200, - khaki: 15787660, - lavender: 15132410, - lavenderblush: 16773365, - lawngreen: 8190976, - lemonchiffon: 16775885, - lightblue: 11393254, - lightcoral: 15761536, - lightcyan: 14745599, - lightgoldenrodyellow: 16448210, - lightgray: 13882323, - lightgreen: 9498256, - lightgrey: 13882323, - lightpink: 16758465, - lightsalmon: 16752762, - lightseagreen: 2142890, - lightskyblue: 8900346, - lightslategray: 7833753, - lightslategrey: 7833753, - lightsteelblue: 11584734, - lightyellow: 16777184, - lime: 65280, - limegreen: 3329330, - linen: 16445670, - magenta: 16711935, - maroon: 8388608, - mediumaquamarine: 6737322, - mediumblue: 205, - mediumorchid: 12211667, - mediumpurple: 9662683, - mediumseagreen: 3978097, - mediumslateblue: 8087790, - mediumspringgreen: 64154, - mediumturquoise: 4772300, - mediumvioletred: 13047173, - midnightblue: 1644912, - mintcream: 16121850, - mistyrose: 16770273, - moccasin: 16770229, - navajowhite: 16768685, - navy: 128, - oldlace: 16643558, - olive: 8421376, - olivedrab: 7048739, - orange: 16753920, - orangered: 16729344, - orchid: 14315734, - palegoldenrod: 15657130, - palegreen: 10025880, - paleturquoise: 11529966, - palevioletred: 14381203, - papayawhip: 16773077, - peachpuff: 16767673, - peru: 13468991, - pink: 16761035, - plum: 14524637, - powderblue: 11591910, - purple: 8388736, - rebeccapurple: 6697881, - red: 16711680, - rosybrown: 12357519, - royalblue: 4286945, - saddlebrown: 9127187, - salmon: 16416882, - sandybrown: 16032864, - seagreen: 3050327, - seashell: 16774638, - sienna: 10506797, - silver: 12632256, - skyblue: 8900331, - slateblue: 6970061, - slategray: 7372944, - slategrey: 7372944, - snow: 16775930, - springgreen: 65407, - steelblue: 4620980, - tan: 13808780, - teal: 32896, - thistle: 14204888, - tomato: 16737095, - turquoise: 4251856, - violet: 15631086, - wheat: 16113331, - white: 16777215, - whitesmoke: 16119285, - yellow: 16776960, - yellowgreen: 10145074 - }); - d3_rgb_names.forEach(function(key, value) { - d3_rgb_names.set(key, d3_rgbNumber(value)); - }); - function d3_functor(v) { - return typeof v === "function" ? v : function() { - return v; - }; - } - d3.functor = d3_functor; - d3.xhr = d3_xhrType(d3_identity); - function d3_xhrType(response) { - return function(url, mimeType, callback) { - if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, - mimeType = null; - return d3_xhr(url, mimeType, response, callback); - }; - } - function d3_xhr(url, mimeType, response, callback) { - var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; - if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); - "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { - request.readyState > 3 && respond(); - }; - function respond() { - var status = request.status, result; - if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { - try { - result = response.call(xhr, request); - } catch (e) { - dispatch.error.call(xhr, e); - return; - } - dispatch.load.call(xhr, result); - } else { - dispatch.error.call(xhr, request); - } - } - request.onprogress = function(event) { - var o = d3.event; - d3.event = event; - try { - dispatch.progress.call(xhr, request); - } finally { - d3.event = o; - } - }; - xhr.header = function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers[name]; - if (value == null) delete headers[name]; else headers[name] = value + ""; - return xhr; - }; - xhr.mimeType = function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return xhr; - }; - xhr.responseType = function(value) { - if (!arguments.length) return responseType; - responseType = value; - return xhr; - }; - xhr.response = function(value) { - response = value; - return xhr; - }; - [ "get", "post" ].forEach(function(method) { - xhr[method] = function() { - return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); - }; - }); - xhr.send = function(method, data, callback) { - if (arguments.length === 2 && typeof data === "function") callback = data, data = null; - request.open(method, url, true); - if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; - if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); - if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); - if (responseType != null) request.responseType = responseType; - if (callback != null) xhr.on("error", callback).on("load", function(request) { - callback(null, request); - }); - dispatch.beforesend.call(xhr, request); - request.send(data == null ? null : data); - return xhr; - }; - xhr.abort = function() { - request.abort(); - return xhr; - }; - d3.rebind(xhr, dispatch, "on"); - return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); - } - function d3_xhr_fixCallback(callback) { - return callback.length === 1 ? function(error, request) { - callback(error == null ? request : null); - } : callback; - } - function d3_xhrHasResponse(request) { - var type = request.responseType; - return type && type !== "text" ? request.response : request.responseText; - } - d3.dsv = function(delimiter, mimeType) { - var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); - function dsv(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); - xhr.row = function(_) { - return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; - }; - return xhr; - } - function response(request) { - return dsv.parse(request.responseText); - } - function typedResponse(f) { - return function(request) { - return dsv.parse(request.responseText, f); - }; - } - dsv.parse = function(text, f) { - var o; - return dsv.parseRows(text, function(row, i) { - if (o) return o(row, i - 1); - var a = new Function("d", "return {" + row.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); - o = f ? function(row, i) { - return f(a(row), i); - } : a; - }); - }; - dsv.parseRows = function(text, f) { - var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; - function token() { - if (I >= N) return EOF; - if (eol) return eol = false, EOL; - var j = I; - if (text.charCodeAt(j) === 34) { - var i = j; - while (i++ < N) { - if (text.charCodeAt(i) === 34) { - if (text.charCodeAt(i + 1) !== 34) break; - ++i; - } - } - I = i + 2; - var c = text.charCodeAt(i + 1); - if (c === 13) { - eol = true; - if (text.charCodeAt(i + 2) === 10) ++I; - } else if (c === 10) { - eol = true; - } - return text.slice(j + 1, i).replace(/""/g, '"'); - } - while (I < N) { - var c = text.charCodeAt(I++), k = 1; - if (c === 10) eol = true; else if (c === 13) { - eol = true; - if (text.charCodeAt(I) === 10) ++I, ++k; - } else if (c !== delimiterCode) continue; - return text.slice(j, I - k); - } - return text.slice(j); - } - while ((t = token()) !== EOF) { - var a = []; - while (t !== EOL && t !== EOF) { - a.push(t); - t = token(); - } - if (f && (a = f(a, n++)) == null) continue; - rows.push(a); - } - return rows; - }; - dsv.format = function(rows) { - if (Array.isArray(rows[0])) return dsv.formatRows(rows); - var fieldSet = new d3_Set(), fields = []; - rows.forEach(function(row) { - for (var field in row) { - if (!fieldSet.has(field)) { - fields.push(fieldSet.add(field)); - } - } - }); - return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { - return fields.map(function(field) { - return formatValue(row[field]); - }).join(delimiter); - })).join("\n"); - }; - dsv.formatRows = function(rows) { - return rows.map(formatRow).join("\n"); - }; - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - function formatValue(text) { - return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; - } - return dsv; - }; - d3.csv = d3.dsv(",", "text/csv"); - d3.tsv = d3.dsv(" ", "text/tab-separated-values"); - var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { - setTimeout(callback, 17); - }; - d3.timer = function() { - d3_timer.apply(this, arguments); - }; - function d3_timer(callback, delay, then) { - var n = arguments.length; - if (n < 2) delay = 0; - if (n < 3) then = Date.now(); - var time = then + delay, timer = { - c: callback, - t: time, - n: null - }; - if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; - d3_timer_queueTail = timer; - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - return timer; - } - function d3_timer_step() { - var now = d3_timer_mark(), delay = d3_timer_sweep() - now; - if (delay > 24) { - if (isFinite(delay)) { - clearTimeout(d3_timer_timeout); - d3_timer_timeout = setTimeout(d3_timer_step, delay); - } - d3_timer_interval = 0; - } else { - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - } - d3.timer.flush = function() { - d3_timer_mark(); - d3_timer_sweep(); - }; - function d3_timer_mark() { - var now = Date.now(), timer = d3_timer_queueHead; - while (timer) { - if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; - timer = timer.n; - } - return now; - } - function d3_timer_sweep() { - var t0, t1 = d3_timer_queueHead, time = Infinity; - while (t1) { - if (t1.c) { - if (t1.t < time) time = t1.t; - t1 = (t0 = t1).n; - } else { - t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; - } - } - d3_timer_queueTail = t0; - return time; - } - function d3_format_precision(x, p) { - return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); - } - d3.round = function(x, n) { - return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); - }; - var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); - d3.formatPrefix = function(value, precision) { - var i = 0; - if (value = +value) { - if (value < 0) value *= -1; - if (precision) value = d3.round(value, d3_format_precision(value, precision)); - i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); - i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); - } - return d3_formatPrefixes[8 + i / 3]; - }; - function d3_formatPrefix(d, i) { - var k = Math.pow(10, abs(8 - i) * 3); - return { - scale: i > 8 ? function(d) { - return d / k; - } : function(d) { - return d * k; - }, - symbol: d - }; - } - function d3_locale_numberFormat(locale) { - var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { - var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; - while (i > 0 && g > 0) { - if (length + g + 1 > width) g = Math.max(1, width - length); - t.push(value.substring(i -= g, i + g)); - if ((length += g + 1) > width) break; - g = locale_grouping[j = (j + 1) % locale_grouping.length]; - } - return t.reverse().join(locale_thousands); - } : d3_identity; - return function(specifier) { - var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; - if (precision) precision = +precision.substring(1); - if (zfill || fill === "0" && align === "=") { - zfill = fill = "0"; - align = "="; - } - switch (type) { - case "n": - comma = true; - type = "g"; - break; - - case "%": - scale = 100; - suffix = "%"; - type = "f"; - break; - - case "p": - scale = 100; - suffix = "%"; - type = "r"; - break; - - case "b": - case "o": - case "x": - case "X": - if (symbol === "#") prefix = "0" + type.toLowerCase(); - - case "c": - exponent = false; - - case "d": - integer = true; - precision = 0; - break; - - case "s": - scale = -1; - type = "r"; - break; - } - if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; - if (type == "r" && !precision) type = "g"; - if (precision != null) { - if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); - } - type = d3_format_types.get(type) || d3_format_typeDefault; - var zcomma = zfill && comma; - return function(value) { - var fullSuffix = suffix; - if (integer && value % 1) return ""; - var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; - if (scale < 0) { - var unit = d3.formatPrefix(value, precision); - value = unit.scale(value); - fullSuffix = unit.symbol + suffix; - } else { - value *= scale; - } - value = type(value, precision); - var i = value.lastIndexOf("."), before, after; - if (i < 0) { - var j = exponent ? value.lastIndexOf("e") : -1; - if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); - } else { - before = value.substring(0, i); - after = locale_decimal + value.substring(i + 1); - } - if (!zfill && comma) before = formatGroup(before, Infinity); - var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; - if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); - negative += prefix; - value = before + after; - return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; - }; - }; - } - var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; - var d3_format_types = d3.map({ - b: function(x) { - return x.toString(2); - }, - c: function(x) { - return String.fromCharCode(x); - }, - o: function(x) { - return x.toString(8); - }, - x: function(x) { - return x.toString(16); - }, - X: function(x) { - return x.toString(16).toUpperCase(); - }, - g: function(x, p) { - return x.toPrecision(p); - }, - e: function(x, p) { - return x.toExponential(p); - }, - f: function(x, p) { - return x.toFixed(p); - }, - r: function(x, p) { - return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); - } - }); - function d3_format_typeDefault(x) { - return x + ""; - } - var d3_time = d3.time = {}, d3_date = Date; - function d3_date_utc() { - this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); - } - d3_date_utc.prototype = { - getDate: function() { - return this._.getUTCDate(); - }, - getDay: function() { - return this._.getUTCDay(); - }, - getFullYear: function() { - return this._.getUTCFullYear(); - }, - getHours: function() { - return this._.getUTCHours(); - }, - getMilliseconds: function() { - return this._.getUTCMilliseconds(); - }, - getMinutes: function() { - return this._.getUTCMinutes(); - }, - getMonth: function() { - return this._.getUTCMonth(); - }, - getSeconds: function() { - return this._.getUTCSeconds(); - }, - getTime: function() { - return this._.getTime(); - }, - getTimezoneOffset: function() { - return 0; - }, - valueOf: function() { - return this._.valueOf(); - }, - setDate: function() { - d3_time_prototype.setUTCDate.apply(this._, arguments); - }, - setDay: function() { - d3_time_prototype.setUTCDay.apply(this._, arguments); - }, - setFullYear: function() { - d3_time_prototype.setUTCFullYear.apply(this._, arguments); - }, - setHours: function() { - d3_time_prototype.setUTCHours.apply(this._, arguments); - }, - setMilliseconds: function() { - d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); - }, - setMinutes: function() { - d3_time_prototype.setUTCMinutes.apply(this._, arguments); - }, - setMonth: function() { - d3_time_prototype.setUTCMonth.apply(this._, arguments); - }, - setSeconds: function() { - d3_time_prototype.setUTCSeconds.apply(this._, arguments); - }, - setTime: function() { - d3_time_prototype.setTime.apply(this._, arguments); - } - }; - var d3_time_prototype = Date.prototype; - function d3_time_interval(local, step, number) { - function round(date) { - var d0 = local(date), d1 = offset(d0, 1); - return date - d0 < d1 - date ? d0 : d1; - } - function ceil(date) { - step(date = local(new d3_date(date - 1)), 1); - return date; - } - function offset(date, k) { - step(date = new d3_date(+date), k); - return date; - } - function range(t0, t1, dt) { - var time = ceil(t0), times = []; - if (dt > 1) { - while (time < t1) { - if (!(number(time) % dt)) times.push(new Date(+time)); - step(time, 1); - } - } else { - while (time < t1) times.push(new Date(+time)), step(time, 1); - } - return times; - } - function range_utc(t0, t1, dt) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = t0; - return range(utc, t1, dt); - } finally { - d3_date = Date; - } - } - local.floor = local; - local.round = round; - local.ceil = ceil; - local.offset = offset; - local.range = range; - var utc = local.utc = d3_time_interval_utc(local); - utc.floor = utc; - utc.round = d3_time_interval_utc(round); - utc.ceil = d3_time_interval_utc(ceil); - utc.offset = d3_time_interval_utc(offset); - utc.range = range_utc; - return local; - } - function d3_time_interval_utc(method) { - return function(date, k) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = date; - return method(utc, k)._; - } finally { - d3_date = Date; - } - }; - } - d3_time.year = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setMonth(0, 1); - return date; - }, function(date, offset) { - date.setFullYear(date.getFullYear() + offset); - }, function(date) { - return date.getFullYear(); - }); - d3_time.years = d3_time.year.range; - d3_time.years.utc = d3_time.year.utc.range; - d3_time.day = d3_time_interval(function(date) { - var day = new d3_date(2e3, 0); - day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - return day; - }, function(date, offset) { - date.setDate(date.getDate() + offset); - }, function(date) { - return date.getDate() - 1; - }); - d3_time.days = d3_time.day.range; - d3_time.days.utc = d3_time.day.utc.range; - d3_time.dayOfYear = function(date) { - var year = d3_time.year(date); - return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); - }; - [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { - i = 7 - i; - var interval = d3_time[day] = d3_time_interval(function(date) { - (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); - return date; - }, function(date, offset) { - date.setDate(date.getDate() + Math.floor(offset) * 7); - }, function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); - }); - d3_time[day + "s"] = interval.range; - d3_time[day + "s"].utc = interval.utc.range; - d3_time[day + "OfYear"] = function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); - }; - }); - d3_time.week = d3_time.sunday; - d3_time.weeks = d3_time.sunday.range; - d3_time.weeks.utc = d3_time.sunday.utc.range; - d3_time.weekOfYear = d3_time.sundayOfYear; - function d3_locale_timeFormat(locale) { - var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; - function d3_time_format(template) { - var n = template.length; - function format(date) { - var string = [], i = -1, j = 0, c, p, f; - while (++i < n) { - if (template.charCodeAt(i) === 37) { - string.push(template.slice(j, i)); - if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); - if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); - string.push(c); - j = i + 1; - } - } - string.push(template.slice(j, i)); - return string.join(""); - } - format.parse = function(string) { - var d = { - y: 1900, - m: 0, - d: 1, - H: 0, - M: 0, - S: 0, - L: 0, - Z: null - }, i = d3_time_parse(d, template, string, 0); - if (i != string.length) return null; - if ("p" in d) d.H = d.H % 12 + d.p * 12; - var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); - if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { - if (!("w" in d)) d.w = "W" in d ? 1 : 0; - date.setFullYear(d.y, 0, 1); - date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); - } else date.setFullYear(d.y, d.m, d.d); - date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); - return localZ ? date._ : date; - }; - format.toString = function() { - return template; - }; - return format; - } - function d3_time_parse(date, template, string, j) { - var c, p, t, i = 0, n = template.length, m = string.length; - while (i < n) { - if (j >= m) return -1; - c = template.charCodeAt(i++); - if (c === 37) { - t = template.charAt(i++); - p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; - if (!p || (j = p(date, string, j)) < 0) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - return j; - } - d3_time_format.utc = function(template) { - var local = d3_time_format(template); - function format(date) { - try { - d3_date = d3_date_utc; - var utc = new d3_date(); - utc._ = date; - return local(utc); - } finally { - d3_date = Date; - } - } - format.parse = function(string) { - try { - d3_date = d3_date_utc; - var date = local.parse(string); - return date && date._; - } finally { - d3_date = Date; - } - }; - format.toString = local.toString; - return format; - }; - d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; - var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); - locale_periods.forEach(function(p, i) { - d3_time_periodLookup.set(p.toLowerCase(), i); - }); - var d3_time_formats = { - a: function(d) { - return locale_shortDays[d.getDay()]; - }, - A: function(d) { - return locale_days[d.getDay()]; - }, - b: function(d) { - return locale_shortMonths[d.getMonth()]; - }, - B: function(d) { - return locale_months[d.getMonth()]; - }, - c: d3_time_format(locale_dateTime), - d: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - e: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - H: function(d, p) { - return d3_time_formatPad(d.getHours(), p, 2); - }, - I: function(d, p) { - return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); - }, - j: function(d, p) { - return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); - }, - L: function(d, p) { - return d3_time_formatPad(d.getMilliseconds(), p, 3); - }, - m: function(d, p) { - return d3_time_formatPad(d.getMonth() + 1, p, 2); - }, - M: function(d, p) { - return d3_time_formatPad(d.getMinutes(), p, 2); - }, - p: function(d) { - return locale_periods[+(d.getHours() >= 12)]; - }, - S: function(d, p) { - return d3_time_formatPad(d.getSeconds(), p, 2); - }, - U: function(d, p) { - return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); - }, - w: function(d) { - return d.getDay(); - }, - W: function(d, p) { - return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); - }, - x: d3_time_format(locale_date), - X: d3_time_format(locale_time), - y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 100, p, 2); - }, - Y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); - }, - Z: d3_time_zone, - "%": function() { - return "%"; - } - }; - var d3_time_parsers = { - a: d3_time_parseWeekdayAbbrev, - A: d3_time_parseWeekday, - b: d3_time_parseMonthAbbrev, - B: d3_time_parseMonth, - c: d3_time_parseLocaleFull, - d: d3_time_parseDay, - e: d3_time_parseDay, - H: d3_time_parseHour24, - I: d3_time_parseHour24, - j: d3_time_parseDayOfYear, - L: d3_time_parseMilliseconds, - m: d3_time_parseMonthNumber, - M: d3_time_parseMinutes, - p: d3_time_parseAmPm, - S: d3_time_parseSeconds, - U: d3_time_parseWeekNumberSunday, - w: d3_time_parseWeekdayNumber, - W: d3_time_parseWeekNumberMonday, - x: d3_time_parseLocaleDate, - X: d3_time_parseLocaleTime, - y: d3_time_parseYear, - Y: d3_time_parseFullYear, - Z: d3_time_parseZone, - "%": d3_time_parseLiteralPercent - }; - function d3_time_parseWeekdayAbbrev(date, string, i) { - d3_time_dayAbbrevRe.lastIndex = 0; - var n = d3_time_dayAbbrevRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseWeekday(date, string, i) { - d3_time_dayRe.lastIndex = 0; - var n = d3_time_dayRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonthAbbrev(date, string, i) { - d3_time_monthAbbrevRe.lastIndex = 0; - var n = d3_time_monthAbbrevRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonth(date, string, i) { - d3_time_monthRe.lastIndex = 0; - var n = d3_time_monthRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseLocaleFull(date, string, i) { - return d3_time_parse(date, d3_time_formats.c.toString(), string, i); - } - function d3_time_parseLocaleDate(date, string, i) { - return d3_time_parse(date, d3_time_formats.x.toString(), string, i); - } - function d3_time_parseLocaleTime(date, string, i) { - return d3_time_parse(date, d3_time_formats.X.toString(), string, i); - } - function d3_time_parseAmPm(date, string, i) { - var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); - return n == null ? -1 : (date.p = n, i); - } - return d3_time_format; - } - var d3_time_formatPads = { - "-": "", - _: " ", - "0": "0" - }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; - function d3_time_formatPad(value, fill, width) { - var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); - } - function d3_time_formatRe(names) { - return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); - } - function d3_time_formatLookup(names) { - var map = new d3_Map(), i = -1, n = names.length; - while (++i < n) map.set(names[i].toLowerCase(), i); - return map; - } - function d3_time_parseWeekdayNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 1)); - return n ? (date.w = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberSunday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.U = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberMonday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.W = +n[0], i + n[0].length) : -1; - } - function d3_time_parseFullYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 4)); - return n ? (date.y = +n[0], i + n[0].length) : -1; - } - function d3_time_parseYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; - } - function d3_time_parseZone(date, string, i) { - return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, - i + 5) : -1; - } - function d3_time_expandYear(d) { - return d + (d > 68 ? 1900 : 2e3); - } - function d3_time_parseMonthNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.m = n[0] - 1, i + n[0].length) : -1; - } - function d3_time_parseDay(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.d = +n[0], i + n[0].length) : -1; - } - function d3_time_parseDayOfYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.j = +n[0], i + n[0].length) : -1; - } - function d3_time_parseHour24(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.H = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMinutes(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.M = +n[0], i + n[0].length) : -1; - } - function d3_time_parseSeconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.S = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMilliseconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.L = +n[0], i + n[0].length) : -1; - } - function d3_time_zone(d) { - var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; - return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); - } - function d3_time_parseLiteralPercent(date, string, i) { - d3_time_percentRe.lastIndex = 0; - var n = d3_time_percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; - } - function d3_time_formatMulti(formats) { - var n = formats.length, i = -1; - while (++i < n) formats[i][0] = this(formats[i][0]); - return function(date) { - var i = 0, f = formats[i]; - while (!f[1](date)) f = formats[++i]; - return f[0](date); - }; - } - d3.locale = function(locale) { - return { - numberFormat: d3_locale_numberFormat(locale), - timeFormat: d3_locale_timeFormat(locale) - }; - }; - var d3_locale_enUS = d3.locale({ - decimal: ".", - thousands: ",", - grouping: [ 3 ], - currency: [ "$", "" ], - dateTime: "%a %b %e %X %Y", - date: "%m/%d/%Y", - time: "%H:%M:%S", - periods: [ "AM", "PM" ], - days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], - shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], - months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], - shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] - }); - d3.format = d3_locale_enUS.numberFormat; - d3.geo = {}; - function d3_adder() {} - d3_adder.prototype = { - s: 0, - t: 0, - add: function(y) { - d3_adderSum(y, this.t, d3_adderTemp); - d3_adderSum(d3_adderTemp.s, this.s, this); - if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; - }, - reset: function() { - this.s = this.t = 0; - }, - valueOf: function() { - return this.s; - } - }; - var d3_adderTemp = new d3_adder(); - function d3_adderSum(a, b, o) { - var x = o.s = a + b, bv = x - a, av = x - bv; - o.t = a - av + (b - bv); - } - d3.geo.stream = function(object, listener) { - if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { - d3_geo_streamObjectType[object.type](object, listener); - } else { - d3_geo_streamGeometry(object, listener); - } - }; - function d3_geo_streamGeometry(geometry, listener) { - if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { - d3_geo_streamGeometryType[geometry.type](geometry, listener); - } - } - var d3_geo_streamObjectType = { - Feature: function(feature, listener) { - d3_geo_streamGeometry(feature.geometry, listener); - }, - FeatureCollection: function(object, listener) { - var features = object.features, i = -1, n = features.length; - while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); - } - }; - var d3_geo_streamGeometryType = { - Sphere: function(object, listener) { - listener.sphere(); - }, - Point: function(object, listener) { - object = object.coordinates; - listener.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); - }, - LineString: function(object, listener) { - d3_geo_streamLine(object.coordinates, listener, 0); - }, - MultiLineString: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); - }, - Polygon: function(object, listener) { - d3_geo_streamPolygon(object.coordinates, listener); - }, - MultiPolygon: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); - }, - GeometryCollection: function(object, listener) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) d3_geo_streamGeometry(geometries[i], listener); - } - }; - function d3_geo_streamLine(coordinates, listener, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - listener.lineStart(); - while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); - listener.lineEnd(); - } - function d3_geo_streamPolygon(coordinates, listener) { - var i = -1, n = coordinates.length; - listener.polygonStart(); - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); - listener.polygonEnd(); - } - d3.geo.area = function(object) { - d3_geo_areaSum = 0; - d3.geo.stream(object, d3_geo_area); - return d3_geo_areaSum; - }; - var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); - var d3_geo_area = { - sphere: function() { - d3_geo_areaSum += 4 * π; - }, - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_areaRingSum.reset(); - d3_geo_area.lineStart = d3_geo_areaRingStart; - }, - polygonEnd: function() { - var area = 2 * d3_geo_areaRingSum; - d3_geo_areaSum += area < 0 ? 4 * π + area : area; - d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; - } - }; - function d3_geo_areaRingStart() { - var λ00, φ00, λ0, cosφ0, sinφ0; - d3_geo_area.point = function(λ, φ) { - d3_geo_area.point = nextPoint; - λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), - sinφ0 = Math.sin(φ); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - φ = φ * d3_radians / 2 + π / 4; - var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); - d3_geo_areaRingSum.add(Math.atan2(v, u)); - λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; - } - d3_geo_area.lineEnd = function() { - nextPoint(λ00, φ00); - }; - } - function d3_geo_cartesian(spherical) { - var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); - return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; - } - function d3_geo_cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; - } - function d3_geo_cartesianCross(a, b) { - return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; - } - function d3_geo_cartesianAdd(a, b) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; - } - function d3_geo_cartesianScale(vector, k) { - return [ vector[0] * k, vector[1] * k, vector[2] * k ]; - } - function d3_geo_cartesianNormalize(d) { - var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l; - d[1] /= l; - d[2] /= l; - } - function d3_geo_spherical(cartesian) { - return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; - } - function d3_geo_sphericalEqual(a, b) { - return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; - } - d3.geo.bounds = function() { - var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; - var bound = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - bound.point = ringPoint; - bound.lineStart = ringStart; - bound.lineEnd = ringEnd; - dλSum = 0; - d3_geo_area.polygonStart(); - }, - polygonEnd: function() { - d3_geo_area.polygonEnd(); - bound.point = point; - bound.lineStart = lineStart; - bound.lineEnd = lineEnd; - if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; - range[0] = λ0, range[1] = λ1; - } - }; - function point(λ, φ) { - ranges.push(range = [ λ0 = λ, λ1 = λ ]); - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - function linePoint(λ, φ) { - var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); - if (p0) { - var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); - d3_geo_cartesianNormalize(inflection); - inflection = d3_geo_spherical(inflection); - var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; - if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = inflection[1] * d3_degrees; - if (φi > φ1) φ1 = φi; - } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = -inflection[1] * d3_degrees; - if (φi < φ0) φ0 = φi; - } else { - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - if (antimeridian) { - if (λ < λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } else { - if (λ1 >= λ0) { - if (λ < λ0) λ0 = λ; - if (λ > λ1) λ1 = λ; - } else { - if (λ > λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } - } - } else { - point(λ, φ); - } - p0 = p, λ_ = λ; - } - function lineStart() { - bound.point = linePoint; - } - function lineEnd() { - range[0] = λ0, range[1] = λ1; - bound.point = point; - p0 = null; - } - function ringPoint(λ, φ) { - if (p0) { - var dλ = λ - λ_; - dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; - } else λ__ = λ, φ__ = φ; - d3_geo_area.point(λ, φ); - linePoint(λ, φ); - } - function ringStart() { - d3_geo_area.lineStart(); - } - function ringEnd() { - ringPoint(λ__, φ__); - d3_geo_area.lineEnd(); - if (abs(dλSum) > ε) λ0 = -(λ1 = 180); - range[0] = λ0, range[1] = λ1; - p0 = null; - } - function angle(λ0, λ1) { - return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; - } - function compareRanges(a, b) { - return a[0] - b[0]; - } - function withinRange(x, range) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; - } - return function(feature) { - φ1 = λ1 = -(λ0 = φ0 = Infinity); - ranges = []; - d3.geo.stream(feature, bound); - var n = ranges.length; - if (n) { - ranges.sort(compareRanges); - for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { - b = ranges[i]; - if (withinRange(b[0], a) || withinRange(b[1], a)) { - if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; - if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; - } else { - merged.push(a = b); - } - } - var best = -Infinity, dλ; - for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { - b = merged[i]; - if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; - } - } - ranges = range = null; - return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; - }; - }(); - d3.geo.centroid = function(object) { - d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, d3_geo_centroid); - var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; - if (m < ε2) { - x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; - if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; - m = x * x + y * y + z * z; - if (m < ε2) return [ NaN, NaN ]; - } - return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; - }; - var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; - var d3_geo_centroid = { - sphere: d3_noop, - point: d3_geo_centroidPoint, - lineStart: d3_geo_centroidLineStart, - lineEnd: d3_geo_centroidLineEnd, - polygonStart: function() { - d3_geo_centroid.lineStart = d3_geo_centroidRingStart; - }, - polygonEnd: function() { - d3_geo_centroid.lineStart = d3_geo_centroidLineStart; - } - }; - function d3_geo_centroidPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); - } - function d3_geo_centroidPointXYZ(x, y, z) { - ++d3_geo_centroidW0; - d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; - d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; - d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; - } - function d3_geo_centroidLineStart() { - var x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroid.point = nextPoint; - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_centroidLineEnd() { - d3_geo_centroid.point = d3_geo_centroidPoint; - } - function d3_geo_centroidRingStart() { - var λ00, φ00, x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ00 = λ, φ00 = φ; - d3_geo_centroid.point = nextPoint; - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - d3_geo_centroid.lineEnd = function() { - nextPoint(λ00, φ00); - d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; - d3_geo_centroid.point = d3_geo_centroidPoint; - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); - d3_geo_centroidX2 += v * cx; - d3_geo_centroidY2 += v * cy; - d3_geo_centroidZ2 += v * cz; - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_compose(a, b) { - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); - }; - return compose; - } - function d3_true() { - return true; - } - function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { - var subject = [], clip = []; - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n]; - if (d3_geo_sphericalEqual(p0, p1)) { - listener.lineStart(); - for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); - listener.lineEnd(); - return; - } - var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); - a.o = b; - subject.push(a); - clip.push(b); - a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); - b = new d3_geo_clipPolygonIntersection(p1, null, a, true); - a.o = b; - subject.push(a); - clip.push(b); - }); - clip.sort(compare); - d3_geo_clipPolygonLinkCircular(subject); - d3_geo_clipPolygonLinkCircular(clip); - if (!subject.length) return; - for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { - clip[i].e = entry = !entry; - } - var start = subject[0], points, point; - while (1) { - var current = start, isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - listener.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, listener); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, listener); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - listener.lineEnd(); - } - } - function d3_geo_clipPolygonLinkCircular(array) { - if (!(n = array.length)) return; - var n, i = 0, a = array[0], b; - while (++i < n) { - a.n = b = array[i]; - b.p = a; - a = b; - } - a.n = b = array[0]; - b.p = a; - } - function d3_geo_clipPolygonIntersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; - this.e = entry; - this.v = false; - this.n = this.p = null; - } - function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { - return function(rotate, listener) { - var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - segments = []; - polygon = []; - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = d3.merge(segments); - var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); - if (segments.length) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); - } else if (clipStartInside) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (polygonStarted) listener.polygonEnd(), polygonStarted = false; - segments = polygon = null; - }, - sphere: function() { - listener.polygonStart(); - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - listener.polygonEnd(); - } - }; - function point(λ, φ) { - var point = rotate(λ, φ); - if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); - } - function pointLine(λ, φ) { - var point = rotate(λ, φ); - line.point(point[0], point[1]); - } - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } - function lineEnd() { - clip.point = point; - line.lineEnd(); - } - var segments; - var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; - function pointRing(λ, φ) { - ring.push([ λ, φ ]); - var point = rotate(λ, φ); - ringListener.point(point[0], point[1]); - } - function ringStart() { - ringListener.lineStart(); - ring = []; - } - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringListener.lineEnd(); - var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; - ring.pop(); - polygon.push(ring); - ring = null; - if (!n) return; - if (clean & 1) { - segment = ringSegments[0]; - var n = segment.length - 1, i = -1, point; - if (n > 0) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - while (++i < n) listener.point((point = segment[i])[0], point[1]); - listener.lineEnd(); - } - return; - } - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); - segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); - } - return clip; - }; - } - function d3_geo_clipSegmentLength1(segment) { - return segment.length > 1; - } - function d3_geo_clipBufferListener() { - var lines = [], line; - return { - lineStart: function() { - lines.push(line = []); - }, - point: function(λ, φ) { - line.push([ λ, φ ]); - }, - lineEnd: d3_noop, - buffer: function() { - var buffer = lines; - lines = []; - line = null; - return buffer; - }, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - } - }; - } - function d3_geo_clipSort(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); - } - var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); - function d3_geo_clipAntimeridianLine(listener) { - var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; - return { - lineStart: function() { - listener.lineStart(); - clean = 1; - }, - point: function(λ1, φ1) { - var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); - if (abs(dλ - π) < ε) { - listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - listener.point(λ1, φ0); - clean = 0; - } else if (sλ0 !== sλ1 && dλ >= π) { - if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; - if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; - φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - clean = 0; - } - listener.point(λ0 = λ1, φ0 = φ1); - sλ0 = sλ1; - }, - lineEnd: function() { - listener.lineEnd(); - λ0 = φ0 = NaN; - }, - clean: function() { - return 2 - clean; - } - }; - } - function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { - var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); - return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; - } - function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { - var φ; - if (from == null) { - φ = direction * halfπ; - listener.point(-π, φ); - listener.point(0, φ); - listener.point(π, φ); - listener.point(π, 0); - listener.point(π, -φ); - listener.point(0, -φ); - listener.point(-π, -φ); - listener.point(-π, 0); - listener.point(-π, φ); - } else if (abs(from[0] - to[0]) > ε) { - var s = from[0] < to[0] ? π : -π; - φ = direction * s / 2; - listener.point(-s, φ); - listener.point(0, φ); - listener.point(s, φ); - } else { - listener.point(to[0], to[1]); - } - } - function d3_geo_pointInPolygon(point, polygon) { - var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; - d3_geo_areaRingSum.reset(); - for (var i = 0, n = polygon.length; i < n; ++i) { - var ring = polygon[i], m = ring.length; - if (!m) continue; - var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; - while (true) { - if (j === m) j = 0; - point = ring[j]; - var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; - d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); - polarAngle += antimeridian ? dλ + sdλ * τ : dλ; - if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { - var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); - d3_geo_cartesianNormalize(arc); - var intersection = d3_geo_cartesianCross(meridianNormal, arc); - d3_geo_cartesianNormalize(intersection); - var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); - if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { - winding += antimeridian ^ dλ >= 0 ? 1 : -1; - } - } - if (!j++) break; - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; - } - } - return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1; - } - function d3_geo_clipCircle(radius) { - var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); - return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); - function visible(λ, φ) { - return Math.cos(λ) * Math.cos(φ) > cr; - } - function clipLine(listener) { - var point0, c0, v0, v00, clean; - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(λ, φ) { - var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; - if (!point0 && (v00 = v0 = v)) listener.lineStart(); - if (v !== v0) { - point2 = intersect(point0, point1); - if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { - point1[0] += ε; - point1[1] += ε; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - listener.lineStart(); - point2 = intersect(point1, point0); - listener.point(point2[0], point2[1]); - } else { - point2 = intersect(point0, point1); - listener.point(point2[0], point2[1]); - listener.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - } else { - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { - listener.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) listener.lineEnd(); - point0 = null; - }, - clean: function() { - return clean | (v00 && v0) << 1; - } - }; - } - function intersect(a, b, two) { - var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); - var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; - if (!determinant) return !two && a; - var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); - d3_geo_cartesianAdd(A, B); - var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); - if (t2 < 0) return; - var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); - d3_geo_cartesianAdd(q, A); - q = d3_geo_spherical(q); - if (!two) return q; - var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; - if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; - var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; - if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; - if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { - var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); - d3_geo_cartesianAdd(q1, A); - return [ q, d3_geo_spherical(q1) ]; - } - } - function code(λ, φ) { - var r = smallRadius ? radius : π - radius, code = 0; - if (λ < -r) code |= 1; else if (λ > r) code |= 2; - if (φ < -r) code |= 4; else if (φ > r) code |= 8; - return code; - } - } - function d3_geom_clipLine(x0, y0, x1, y1) { - return function(line) { - var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - if (t0 > 0) line.a = { - x: ax + t0 * dx, - y: ay + t0 * dy - }; - if (t1 < 1) line.b = { - x: ax + t1 * dx, - y: ay + t1 * dy - }; - return line; - }; - } - var d3_geo_clipExtentMAX = 1e9; - d3.geo.clipExtent = function() { - var x0, y0, x1, y1, stream, clip, clipExtent = { - stream: function(output) { - if (stream) stream.valid = false; - stream = clip(output); - stream.valid = true; - return stream; - }, - extent: function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); - if (stream) stream.valid = false, stream = null; - return clipExtent; - } - }; - return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); - }; - function d3_geo_clipExtent(x0, y0, x1, y1) { - return function(listener) { - var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - listener = bufferListener; - segments = []; - polygon = []; - clean = true; - }, - polygonEnd: function() { - listener = listener_; - segments = d3.merge(segments); - var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; - if (inside || visible) { - listener.polygonStart(); - if (inside) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (visible) { - d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); - } - listener.polygonEnd(); - } - segments = polygon = ring = null; - } - }; - function insidePolygon(p) { - var wn = 0, n = polygon.length, y = p[1]; - for (var i = 0; i < n; ++i) { - for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { - b = v[j]; - if (a[1] <= y) { - if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; - } else { - if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; - } - a = b; - } - } - return wn !== 0; - } - function interpolate(from, to, direction, listener) { - var a = 0, a1 = 0; - if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { - do { - listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - } while ((a = (a + direction + 4) % 4) !== a1); - } else { - listener.point(to[0], to[1]); - } - } - function pointVisible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } - function point(x, y) { - if (pointVisible(x, y)) listener.point(x, y); - } - var x__, y__, v__, x_, y_, v_, first, clean; - function lineStart() { - clip.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferListener.rejoin(); - segments.push(bufferListener.buffer()); - } - clip.point = point; - if (v_) listener.lineEnd(); - } - function linePoint(x, y) { - x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); - y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); - var v = pointVisible(x, y); - if (polygon) ring.push([ x, y ]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - listener.lineStart(); - listener.point(x, y); - } - } else { - if (v && v_) listener.point(x, y); else { - var l = { - a: { - x: x_, - y: y_ - }, - b: { - x: x, - y: y - } - }; - if (clipLine(l)) { - if (!v_) { - listener.lineStart(); - listener.point(l.a.x, l.a.y); - } - listener.point(l.b.x, l.b.y); - if (!v) listener.lineEnd(); - clean = false; - } else if (v) { - listener.lineStart(); - listener.point(x, y); - clean = false; - } - } - } - x_ = x, y_ = y, v_ = v; - } - return clip; - }; - function corner(p, direction) { - return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; - } - function compare(a, b) { - return comparePoints(a.x, b.x); - } - function comparePoints(a, b) { - var ca = corner(a, 1), cb = corner(b, 1); - return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; - } - } - function d3_geo_conic(projectAt) { - var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); - p.parallels = function(_) { - if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; - return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); - }; - return p; - } - function d3_geo_conicEqualArea(φ0, φ1) { - var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; - function forward(λ, φ) { - var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; - return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = ρ0 - y; - return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; - }; - return forward; - } - (d3.geo.conicEqualArea = function() { - return d3_geo_conic(d3_geo_conicEqualArea); - }).raw = d3_geo_conicEqualArea; - d3.geo.albers = function() { - return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); - }; - d3.geo.albersUsa = function() { - var lower48 = d3.geo.albers(); - var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); - var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); - var point, pointStream = { - point: function(x, y) { - point = [ x, y ]; - } - }, lower48Point, alaskaPoint, hawaiiPoint; - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - point = null; - (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); - return point; - } - albersUsa.invert = function(coordinates) { - var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; - return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); - }; - albersUsa.stream = function(stream) { - var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); - return { - point: function(x, y) { - lower48Stream.point(x, y); - alaskaStream.point(x, y); - hawaiiStream.point(x, y); - }, - sphere: function() { - lower48Stream.sphere(); - alaskaStream.sphere(); - hawaiiStream.sphere(); - }, - lineStart: function() { - lower48Stream.lineStart(); - alaskaStream.lineStart(); - hawaiiStream.lineStart(); - }, - lineEnd: function() { - lower48Stream.lineEnd(); - alaskaStream.lineEnd(); - hawaiiStream.lineEnd(); - }, - polygonStart: function() { - lower48Stream.polygonStart(); - alaskaStream.polygonStart(); - hawaiiStream.polygonStart(); - }, - polygonEnd: function() { - lower48Stream.polygonEnd(); - alaskaStream.polygonEnd(); - hawaiiStream.polygonEnd(); - } - }; - }; - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_); - alaska.precision(_); - hawaii.precision(_); - return albersUsa; - }; - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_); - alaska.scale(_ * .35); - hawaii.scale(_); - return albersUsa.translate(lower48.translate()); - }; - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; - alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - return albersUsa; - }; - return albersUsa.scale(1070); - }; - var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_pathAreaPolygon = 0; - d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; - }, - polygonEnd: function() { - d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; - d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); - } - }; - function d3_geo_pathAreaRingStart() { - var x00, y00, x0, y0; - d3_geo_pathArea.point = function(x, y) { - d3_geo_pathArea.point = nextPoint; - x00 = x0 = x, y00 = y0 = y; - }; - function nextPoint(x, y) { - d3_geo_pathAreaPolygon += y0 * x - x0 * y; - x0 = x, y0 = y; - } - d3_geo_pathArea.lineEnd = function() { - nextPoint(x00, y00); - }; - } - var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; - var d3_geo_pathBounds = { - point: d3_geo_pathBoundsPoint, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_pathBoundsPoint(x, y) { - if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; - if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; - if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; - if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; - } - function d3_geo_pathBuffer() { - var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointCircle = d3_geo_pathBufferCircle(_); - return stream; - }, - result: function() { - if (buffer.length) { - var result = buffer.join(""); - buffer = []; - return result; - } - } - }; - function point(x, y) { - buffer.push("M", x, ",", y, pointCircle); - } - function pointLineStart(x, y) { - buffer.push("M", x, ",", y); - stream.point = pointLine; - } - function pointLine(x, y) { - buffer.push("L", x, ",", y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - buffer.push("Z"); - } - return stream; - } - function d3_geo_pathBufferCircle(radius) { - return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; - } - var d3_geo_pathCentroid = { - point: d3_geo_pathCentroidPoint, - lineStart: d3_geo_pathCentroidLineStart, - lineEnd: d3_geo_pathCentroidLineEnd, - polygonStart: function() { - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; - }, - polygonEnd: function() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; - d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; - } - }; - function d3_geo_pathCentroidPoint(x, y) { - d3_geo_centroidX0 += x; - d3_geo_centroidY0 += y; - ++d3_geo_centroidZ0; - } - function d3_geo_pathCentroidLineStart() { - var x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - } - function d3_geo_pathCentroidLineEnd() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - } - function d3_geo_pathCentroidRingStart() { - var x00, y00, x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - z = y0 * x - x0 * y; - d3_geo_centroidX2 += z * (x0 + x); - d3_geo_centroidY2 += z * (y0 + y); - d3_geo_centroidZ2 += z * 3; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - d3_geo_pathCentroid.lineEnd = function() { - nextPoint(x00, y00); - }; - } - function d3_geo_pathContext(context) { - var pointRadius = 4.5; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointRadius = _; - return stream; - }, - result: d3_noop - }; - function point(x, y) { - context.moveTo(x + pointRadius, y); - context.arc(x, y, pointRadius, 0, τ); - } - function pointLineStart(x, y) { - context.moveTo(x, y); - stream.point = pointLine; - } - function pointLine(x, y) { - context.lineTo(x, y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - context.closePath(); - } - return stream; - } - function d3_geo_resample(project) { - var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; - function resample(stream) { - return (maxDepth ? resampleRecursive : resampleNone)(stream); - } - function resampleNone(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - }); - } - function resampleRecursive(stream) { - var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; - var resample = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - stream.polygonStart(); - resample.lineStart = ringStart; - }, - polygonEnd: function() { - stream.polygonEnd(); - resample.lineStart = lineStart; - } - }; - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } - function lineStart() { - x0 = NaN; - resample.point = linePoint; - stream.lineStart(); - } - function linePoint(λ, φ) { - var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); - resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } - function lineEnd() { - resample.point = point; - stream.lineEnd(); - } - function ringStart() { - lineStart(); - resample.point = ringPoint; - resample.lineEnd = ringEnd; - } - function ringPoint(λ, φ) { - linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resample.point = linePoint; - } - function ringEnd() { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); - resample.lineEnd = lineEnd; - lineEnd(); - } - return resample; - } - function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; - if (d2 > 4 * δ2 && depth--) { - var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); - } - } - } - resample.precision = function(_) { - if (!arguments.length) return Math.sqrt(δ2); - maxDepth = (δ2 = _ * _) > 0 && 16; - return resample; - }; - return resample; - } - d3.geo.path = function() { - var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); - d3.geo.stream(object, cacheStream); - } - return contextStream.result(); - } - path.area = function(object) { - d3_geo_pathAreaSum = 0; - d3.geo.stream(object, projectStream(d3_geo_pathArea)); - return d3_geo_pathAreaSum; - }; - path.centroid = function(object) { - d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); - return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; - }; - path.bounds = function(object) { - d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); - d3.geo.stream(object, projectStream(d3_geo_pathBounds)); - return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; - }; - path.projection = function(_) { - if (!arguments.length) return projection; - projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; - return reset(); - }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return reset(); - }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; - }; - function reset() { - cacheStream = null; - return path; - } - return path.projection(d3.geo.albersUsa()).context(null); - }; - function d3_geo_pathProjectStream(project) { - var resample = d3_geo_resample(function(x, y) { - return project([ x * d3_degrees, y * d3_degrees ]); - }); - return function(stream) { - return d3_geo_projectionRadians(resample(stream)); - }; - } - d3.geo.transform = function(methods) { - return { - stream: function(stream) { - var transform = new d3_geo_transform(stream); - for (var k in methods) transform[k] = methods[k]; - return transform; - } - }; - }; - function d3_geo_transform(stream) { - this.stream = stream; - } - d3_geo_transform.prototype = { - point: function(x, y) { - this.stream.point(x, y); - }, - sphere: function() { - this.stream.sphere(); - }, - lineStart: function() { - this.stream.lineStart(); - }, - lineEnd: function() { - this.stream.lineEnd(); - }, - polygonStart: function() { - this.stream.polygonStart(); - }, - polygonEnd: function() { - this.stream.polygonEnd(); - } - }; - function d3_geo_transformPoint(stream, point) { - return { - point: point, - sphere: function() { - stream.sphere(); - }, - lineStart: function() { - stream.lineStart(); - }, - lineEnd: function() { - stream.lineEnd(); - }, - polygonStart: function() { - stream.polygonStart(); - }, - polygonEnd: function() { - stream.polygonEnd(); - } - }; - } - d3.geo.projection = d3_geo_projection; - d3.geo.projectionMutator = d3_geo_projectionMutator; - function d3_geo_projection(project) { - return d3_geo_projectionMutator(function() { - return project; - })(); - } - function d3_geo_projectionMutator(projectAt) { - var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { - x = project(x, y); - return [ x[0] * k + δx, δy - x[1] * k ]; - }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; - function projection(point) { - point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); - return [ point[0] * k + δx, δy - point[1] * k ]; - } - function invert(point) { - point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); - return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; - } - projection.stream = function(output) { - if (stream) stream.valid = false; - stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); - stream.valid = true; - return stream; - }; - projection.clipAngle = function(_) { - if (!arguments.length) return clipAngle; - preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); - return invalidate(); - }; - projection.clipExtent = function(_) { - if (!arguments.length) return clipExtent; - clipExtent = _; - postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; - return invalidate(); - }; - projection.scale = function(_) { - if (!arguments.length) return k; - k = +_; - return reset(); - }; - projection.translate = function(_) { - if (!arguments.length) return [ x, y ]; - x = +_[0]; - y = +_[1]; - return reset(); - }; - projection.center = function(_) { - if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; - λ = _[0] % 360 * d3_radians; - φ = _[1] % 360 * d3_radians; - return reset(); - }; - projection.rotate = function(_) { - if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; - δλ = _[0] % 360 * d3_radians; - δφ = _[1] % 360 * d3_radians; - δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; - return reset(); - }; - d3.rebind(projection, projectResample, "precision"); - function reset() { - projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); - var center = project(λ, φ); - δx = x - center[0] * k; - δy = y + center[1] * k; - return invalidate(); - } - function invalidate() { - if (stream) stream.valid = false, stream = null; - return projection; - } - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return reset(); - }; - } - function d3_geo_projectionRadians(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - stream.point(x * d3_radians, y * d3_radians); - }); - } - function d3_geo_equirectangular(λ, φ) { - return [ λ, φ ]; - } - (d3.geo.equirectangular = function() { - return d3_geo_projection(d3_geo_equirectangular); - }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; - d3.geo.rotation = function(rotate) { - rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); - function forward(coordinates) { - coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - } - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - }; - return forward; - }; - function d3_geo_identityRotation(λ, φ) { - return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - } - d3_geo_identityRotation.invert = d3_geo_equirectangular; - function d3_geo_rotation(δλ, δφ, δγ) { - return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; - } - function d3_geo_forwardRotationλ(δλ) { - return function(λ, φ) { - return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - }; - } - function d3_geo_rotationλ(δλ) { - var rotation = d3_geo_forwardRotationλ(δλ); - rotation.invert = d3_geo_forwardRotationλ(-δλ); - return rotation; - } - function d3_geo_rotationφγ(δφ, δγ) { - var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); - function rotation(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; - return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; - } - rotation.invert = function(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; - return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; - }; - return rotation; - } - d3.geo.circle = function() { - var origin = [ 0, 0 ], angle, precision = 6, interpolate; - function circle() { - var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; - interpolate(null, null, 1, { - point: function(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= d3_degrees, x[1] *= d3_degrees; - } - }); - return { - type: "Polygon", - coordinates: [ ring ] - }; - } - circle.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return circle; - }; - circle.angle = function(x) { - if (!arguments.length) return angle; - interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); - return circle; - }; - circle.precision = function(_) { - if (!arguments.length) return precision; - interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); - return circle; - }; - return circle.angle(90); - }; - function d3_geo_circleInterpolate(radius, precision) { - var cr = Math.cos(radius), sr = Math.sin(radius); - return function(from, to, direction, listener) { - var step = direction * precision; - if (from != null) { - from = d3_geo_circleAngle(cr, from); - to = d3_geo_circleAngle(cr, to); - if (direction > 0 ? from < to : from > to) from += direction * τ; - } else { - from = radius + direction * τ; - to = radius - .5 * step; - } - for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { - listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); - } - }; - } - function d3_geo_circleAngle(cr, point) { - var a = d3_geo_cartesian(point); - a[0] -= cr; - d3_geo_cartesianNormalize(a); - var angle = d3_acos(-a[1]); - return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); - } - d3.geo.distance = function(a, b) { - var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; - return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); - }; - d3.geo.graticule = function() { - var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; - function graticule() { - return { - type: "MultiLineString", - coordinates: lines() - }; - } - function lines() { - return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { - return abs(x % DX) > ε; - }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { - return abs(y % DY) > ε; - }).map(y)); - } - graticule.lines = function() { - return lines().map(function(coordinates) { - return { - type: "LineString", - coordinates: coordinates - }; - }); - }; - graticule.outline = function() { - return { - type: "Polygon", - coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] - }; - }; - graticule.extent = function(_) { - if (!arguments.length) return graticule.minorExtent(); - return graticule.majorExtent(_).minorExtent(_); - }; - graticule.majorExtent = function(_) { - if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; - X0 = +_[0][0], X1 = +_[1][0]; - Y0 = +_[0][1], Y1 = +_[1][1]; - if (X0 > X1) _ = X0, X0 = X1, X1 = _; - if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; - return graticule.precision(precision); - }; - graticule.minorExtent = function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - x0 = +_[0][0], x1 = +_[1][0]; - y0 = +_[0][1], y1 = +_[1][1]; - if (x0 > x1) _ = x0, x0 = x1, x1 = _; - if (y0 > y1) _ = y0, y0 = y1, y1 = _; - return graticule.precision(precision); - }; - graticule.step = function(_) { - if (!arguments.length) return graticule.minorStep(); - return graticule.majorStep(_).minorStep(_); - }; - graticule.majorStep = function(_) { - if (!arguments.length) return [ DX, DY ]; - DX = +_[0], DY = +_[1]; - return graticule; - }; - graticule.minorStep = function(_) { - if (!arguments.length) return [ dx, dy ]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = d3_geo_graticuleX(y0, y1, 90); - y = d3_geo_graticuleY(x0, x1, precision); - X = d3_geo_graticuleX(Y0, Y1, 90); - Y = d3_geo_graticuleY(X0, X1, precision); - return graticule; - }; - return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); - }; - function d3_geo_graticuleX(y0, y1, dy) { - var y = d3.range(y0, y1 - ε, dy).concat(y1); - return function(x) { - return y.map(function(y) { - return [ x, y ]; - }); - }; - } - function d3_geo_graticuleY(x0, x1, dx) { - var x = d3.range(x0, x1 - ε, dx).concat(x1); - return function(y) { - return x.map(function(x) { - return [ x, y ]; - }); - }; - } - function d3_source(d) { - return d.source; - } - function d3_target(d) { - return d.target; - } - d3.geo.greatArc = function() { - var source = d3_source, source_, target = d3_target, target_; - function greatArc() { - return { - type: "LineString", - coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] - }; - } - greatArc.distance = function() { - return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); - }; - greatArc.source = function(_) { - if (!arguments.length) return source; - source = _, source_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.target = function(_) { - if (!arguments.length) return target; - target = _, target_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.precision = function() { - return arguments.length ? greatArc : 0; - }; - return greatArc; - }; - d3.geo.interpolate = function(source, target) { - return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); - }; - function d3_geo_interpolate(x0, y0, x1, y1) { - var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); - var interpolate = d ? function(t) { - var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; - return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; - } : function() { - return [ x0 * d3_degrees, y0 * d3_degrees ]; - }; - interpolate.distance = d; - return interpolate; - } - d3.geo.length = function(object) { - d3_geo_lengthSum = 0; - d3.geo.stream(object, d3_geo_length); - return d3_geo_lengthSum; - }; - var d3_geo_lengthSum; - var d3_geo_length = { - sphere: d3_noop, - point: d3_noop, - lineStart: d3_geo_lengthLineStart, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_lengthLineStart() { - var λ0, sinφ0, cosφ0; - d3_geo_length.point = function(λ, φ) { - λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); - d3_geo_length.point = nextPoint; - }; - d3_geo_length.lineEnd = function() { - d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; - }; - function nextPoint(λ, φ) { - var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); - d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; - } - } - function d3_geo_azimuthal(scale, angle) { - function azimuthal(λ, φ) { - var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); - return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; - } - azimuthal.invert = function(x, y) { - var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); - return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; - }; - return azimuthal; - } - var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { - return Math.sqrt(2 / (1 + cosλcosφ)); - }, function(ρ) { - return 2 * Math.asin(ρ / 2); - }); - (d3.geo.azimuthalEqualArea = function() { - return d3_geo_projection(d3_geo_azimuthalEqualArea); - }).raw = d3_geo_azimuthalEqualArea; - var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { - var c = Math.acos(cosλcosφ); - return c && c / Math.sin(c); - }, d3_identity); - (d3.geo.azimuthalEquidistant = function() { - return d3_geo_projection(d3_geo_azimuthalEquidistant); - }).raw = d3_geo_azimuthalEquidistant; - function d3_geo_conicConformal(φ0, φ1) { - var cosφ0 = Math.cos(φ0), t = function(φ) { - return Math.tan(π / 4 + φ / 2); - }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; - if (!n) return d3_geo_mercator; - function forward(λ, φ) { - if (F > 0) { - if (φ < -halfπ + ε) φ = -halfπ + ε; - } else { - if (φ > halfπ - ε) φ = halfπ - ε; - } - var ρ = F / Math.pow(t(φ), n); - return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); - return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; - }; - return forward; - } - (d3.geo.conicConformal = function() { - return d3_geo_conic(d3_geo_conicConformal); - }).raw = d3_geo_conicConformal; - function d3_geo_conicEquidistant(φ0, φ1) { - var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; - if (abs(n) < ε) return d3_geo_equirectangular; - function forward(λ, φ) { - var ρ = G - φ; - return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = G - y; - return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; - }; - return forward; - } - (d3.geo.conicEquidistant = function() { - return d3_geo_conic(d3_geo_conicEquidistant); - }).raw = d3_geo_conicEquidistant; - var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / cosλcosφ; - }, Math.atan); - (d3.geo.gnomonic = function() { - return d3_geo_projection(d3_geo_gnomonic); - }).raw = d3_geo_gnomonic; - function d3_geo_mercator(λ, φ) { - return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; - } - d3_geo_mercator.invert = function(x, y) { - return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; - }; - function d3_geo_mercatorProjection(project) { - var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; - m.scale = function() { - var v = scale.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.translate = function() { - var v = translate.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.clipExtent = function(_) { - var v = clipExtent.apply(m, arguments); - if (v === m) { - if (clipAuto = _ == null) { - var k = π * scale(), t = translate(); - clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); - } - } else if (clipAuto) { - v = null; - } - return v; - }; - return m.clipExtent(null); - } - (d3.geo.mercator = function() { - return d3_geo_mercatorProjection(d3_geo_mercator); - }).raw = d3_geo_mercator; - var d3_geo_orthographic = d3_geo_azimuthal(function() { - return 1; - }, Math.asin); - (d3.geo.orthographic = function() { - return d3_geo_projection(d3_geo_orthographic); - }).raw = d3_geo_orthographic; - var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / (1 + cosλcosφ); - }, function(ρ) { - return 2 * Math.atan(ρ); - }); - (d3.geo.stereographic = function() { - return d3_geo_projection(d3_geo_stereographic); - }).raw = d3_geo_stereographic; - function d3_geo_transverseMercator(λ, φ) { - return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; - } - d3_geo_transverseMercator.invert = function(x, y) { - return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; - }; - (d3.geo.transverseMercator = function() { - var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; - projection.center = function(_) { - return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); - }; - projection.rotate = function(_) { - return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), - [ _[0], _[1], _[2] - 90 ]); - }; - return rotate([ 0, 0, 90 ]); - }).raw = d3_geo_transverseMercator; - d3.geom = {}; - function d3_geom_pointX(d) { - return d[0]; - } - function d3_geom_pointY(d) { - return d[1]; - } - d3.geom.hull = function(vertices) { - var x = d3_geom_pointX, y = d3_geom_pointY; - if (arguments.length) return hull(vertices); - function hull(data) { - if (data.length < 3) return []; - var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; - for (i = 0; i < n; i++) { - points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); - } - points.sort(d3_geom_hullOrder); - for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); - var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); - var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; - for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); - for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); - return polygon; - } - hull.x = function(_) { - return arguments.length ? (x = _, hull) : x; - }; - hull.y = function(_) { - return arguments.length ? (y = _, hull) : y; - }; - return hull; - }; - function d3_geom_hullUpper(points) { - var n = points.length, hull = [ 0, 1 ], hs = 2; - for (var i = 2; i < n; i++) { - while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; - hull[hs++] = i; - } - return hull.slice(0, hs); - } - function d3_geom_hullOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; - } - d3.geom.polygon = function(coordinates) { - d3_subclass(coordinates, d3_geom_polygonPrototype); - return coordinates; - }; - var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; - d3_geom_polygonPrototype.area = function() { - var i = -1, n = this.length, a, b = this[n - 1], area = 0; - while (++i < n) { - a = b; - b = this[i]; - area += a[1] * b[0] - a[0] * b[1]; - } - return area * .5; - }; - d3_geom_polygonPrototype.centroid = function(k) { - var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; - if (!arguments.length) k = -1 / (6 * this.area()); - while (++i < n) { - a = b; - b = this[i]; - c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; - } - return [ x * k, y * k ]; - }; - d3_geom_polygonPrototype.clip = function(subject) { - var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; - while (++i < n) { - input = subject.slice(); - subject.length = 0; - b = this[i]; - c = input[(m = input.length - closed) - 1]; - j = -1; - while (++j < m) { - d = input[j]; - if (d3_geom_polygonInside(d, a, b)) { - if (!d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - subject.push(d); - } else if (d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - c = d; - } - if (closed) subject.push(subject[0]); - a = b; - } - return subject; - }; - function d3_geom_polygonInside(p, a, b) { - return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); - } - function d3_geom_polygonIntersect(c, d, a, b) { - var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); - return [ x1 + ua * x21, y1 + ua * y21 ]; - } - function d3_geom_polygonClosed(coordinates) { - var a = coordinates[0], b = coordinates[coordinates.length - 1]; - return !(a[0] - b[0] || a[1] - b[1]); - } - var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; - function d3_geom_voronoiBeach() { - d3_geom_voronoiRedBlackNode(this); - this.edge = this.site = this.circle = null; - } - function d3_geom_voronoiCreateBeach(site) { - var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); - beach.site = site; - return beach; - } - function d3_geom_voronoiDetachBeach(beach) { - d3_geom_voronoiDetachCircle(beach); - d3_geom_voronoiBeaches.remove(beach); - d3_geom_voronoiBeachPool.push(beach); - d3_geom_voronoiRedBlackNode(beach); - } - function d3_geom_voronoiRemoveBeach(beach) { - var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { - x: x, - y: y - }, previous = beach.P, next = beach.N, disappearing = [ beach ]; - d3_geom_voronoiDetachBeach(beach); - var lArc = previous; - while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { - previous = lArc.P; - disappearing.unshift(lArc); - d3_geom_voronoiDetachBeach(lArc); - lArc = previous; - } - disappearing.unshift(lArc); - d3_geom_voronoiDetachCircle(lArc); - var rArc = next; - while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { - next = rArc.N; - disappearing.push(rArc); - d3_geom_voronoiDetachBeach(rArc); - rArc = next; - } - disappearing.push(rArc); - d3_geom_voronoiDetachCircle(rArc); - var nArcs = disappearing.length, iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); - } - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiAddBeach(site) { - var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; - while (node) { - dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; - if (dxl > ε) node = node.L; else { - dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); - if (dxr > ε) { - if (!node.R) { - lArc = node; - break; - } - node = node.R; - } else { - if (dxl > -ε) { - lArc = node.P; - rArc = node; - } else if (dxr > -ε) { - lArc = node; - rArc = node.N; - } else { - lArc = rArc = node; - } - break; - } - } - } - var newArc = d3_geom_voronoiCreateBeach(site); - d3_geom_voronoiBeaches.insert(lArc, newArc); - if (!lArc && !rArc) return; - if (lArc === rArc) { - d3_geom_voronoiDetachCircle(lArc); - rArc = d3_geom_voronoiCreateBeach(lArc.site); - d3_geom_voronoiBeaches.insert(newArc, rArc); - newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - return; - } - if (!rArc) { - newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - return; - } - d3_geom_voronoiDetachCircle(lArc); - d3_geom_voronoiDetachCircle(rArc); - var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { - x: (cy * hb - by * hc) / d + ax, - y: (bx * hc - cx * hb) / d + ay - }; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); - rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiLeftBreakPoint(arc, directrix) { - var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; - if (!pby2) return rfocx; - var lArc = arc.P; - if (!lArc) return -Infinity; - site = lArc.site; - var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; - if (!plby2) return lfocx; - var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - return (rfocx + lfocx) / 2; - } - function d3_geom_voronoiRightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); - var site = arc.site; - return site.y === directrix ? site.x : Infinity; - } - function d3_geom_voronoiCell(site) { - this.site = site; - this.edges = []; - } - d3_geom_voronoiCell.prototype.prepare = function() { - var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; - while (iHalfEdge--) { - edge = halfEdges[iHalfEdge].edge; - if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); - } - halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); - return halfEdges.length; - }; - function d3_geom_voronoiCloseCells(extent) { - var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; - while (iCell--) { - cell = cells[iCell]; - if (!cell || !cell.prepare()) continue; - halfEdges = cell.edges; - nHalfEdges = halfEdges.length; - iHalfEdge = 0; - while (iHalfEdge < nHalfEdges) { - end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; - start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; - if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { - halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { - x: x0, - y: abs(x2 - x0) < ε ? y2 : y1 - } : abs(y3 - y1) < ε && x1 - x3 > ε ? { - x: abs(y2 - y1) < ε ? x2 : x1, - y: y1 - } : abs(x3 - x1) < ε && y3 - y0 > ε ? { - x: x1, - y: abs(x2 - x1) < ε ? y2 : y0 - } : abs(y3 - y0) < ε && x3 - x0 > ε ? { - x: abs(y2 - y0) < ε ? x2 : x0, - y: y0 - } : null), cell.site, null)); - ++nHalfEdges; - } - } - } - } - function d3_geom_voronoiHalfEdgeOrder(a, b) { - return b.angle - a.angle; - } - function d3_geom_voronoiCircle() { - d3_geom_voronoiRedBlackNode(this); - this.x = this.y = this.arc = this.site = this.cy = null; - } - function d3_geom_voronoiAttachCircle(arc) { - var lArc = arc.P, rArc = arc.N; - if (!lArc || !rArc) return; - var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; - if (lSite === rSite) return; - var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; - var d = 2 * (ax * cy - ay * cx); - if (d >= -ε2) return; - var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; - var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = cy + Math.sqrt(x * x + y * y); - circle.cy = cy; - arc.circle = circle; - var before = null, node = d3_geom_voronoiCircles._; - while (node) { - if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { - if (node.L) node = node.L; else { - before = node.P; - break; - } - } else { - if (node.R) node = node.R; else { - before = node; - break; - } - } - } - d3_geom_voronoiCircles.insert(before, circle); - if (!before) d3_geom_voronoiFirstCircle = circle; - } - function d3_geom_voronoiDetachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; - d3_geom_voronoiCircles.remove(circle); - d3_geom_voronoiCirclePool.push(circle); - d3_geom_voronoiRedBlackNode(circle); - arc.circle = null; - } - } - function d3_geom_voronoiClipEdges(extent) { - var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; - while (i--) { - e = edges[i]; - if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { - e.a = e.b = null; - edges.splice(i, 1); - } - } - } - function d3_geom_voronoiConnectEdge(edge, extent) { - var vb = edge.b; - if (vb) return true; - var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!va) va = { - x: fx, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: fx, - y: y1 - }; - } else { - if (!va) va = { - x: fx, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: fx, - y: y0 - }; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!va) va = { - x: (y0 - fb) / fm, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: (y1 - fb) / fm, - y: y1 - }; - } else { - if (!va) va = { - x: (y1 - fb) / fm, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: (y0 - fb) / fm, - y: y0 - }; - } - } else { - if (ly < ry) { - if (!va) va = { - x: x0, - y: fm * x0 + fb - }; else if (va.x >= x1) return; - vb = { - x: x1, - y: fm * x1 + fb - }; - } else { - if (!va) va = { - x: x1, - y: fm * x1 + fb - }; else if (va.x < x0) return; - vb = { - x: x0, - y: fm * x0 + fb - }; - } - } - } - edge.a = va; - edge.b = vb; - return true; - } - function d3_geom_voronoiEdge(lSite, rSite) { - this.l = lSite; - this.r = rSite; - this.a = this.b = null; - } - function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, rSite); - d3_geom_voronoiEdges.push(edge); - if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); - if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); - d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); - d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); - return edge; - } - function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, null); - edge.a = va; - edge.b = vb; - d3_geom_voronoiEdges.push(edge); - return edge; - } - function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { - if (!edge.a && !edge.b) { - edge.a = vertex; - edge.l = lSite; - edge.r = rSite; - } else if (edge.l === rSite) { - edge.b = vertex; - } else { - edge.a = vertex; - } - } - function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { - var va = edge.a, vb = edge.b; - this.edge = edge; - this.site = lSite; - this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); - } - d3_geom_voronoiHalfEdge.prototype = { - start: function() { - return this.edge.l === this.site ? this.edge.a : this.edge.b; - }, - end: function() { - return this.edge.l === this.site ? this.edge.b : this.edge.a; - } - }; - function d3_geom_voronoiRedBlackTree() { - this._ = null; - } - function d3_geom_voronoiRedBlackNode(node) { - node.U = node.C = node.L = node.R = node.P = node.N = null; - } - d3_geom_voronoiRedBlackTree.prototype = { - insert: function(after, node) { - var parent, grandpa, uncle; - if (after) { - node.P = after; - node.N = after.N; - if (after.N) after.N.P = node; - after.N = node; - if (after.R) { - after = after.R; - while (after.L) after = after.L; - after.L = node; - } else { - after.R = node; - } - parent = after; - } else if (this._) { - after = d3_geom_voronoiRedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; - } else { - node.P = node.N = null; - this._ = node; - parent = null; - } - node.L = node.R = null; - node.U = parent; - node.C = true; - after = node; - while (parent && parent.C) { - grandpa = parent.U; - if (parent === grandpa.L) { - uncle = grandpa.R; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.R) { - d3_geom_voronoiRedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateRight(this, grandpa); - } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - d3_geom_voronoiRedBlackRotateRight(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, grandpa); - } - } - parent = after.U; - } - this._.C = false; - }, - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; - var parent = node.U, sibling, left = node.L, right = node.R, next, red; - if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); - if (parent) { - if (parent.L === node) parent.L = next; else parent.R = next; - } else { - this._ = next; - } - if (left && right) { - red = next.C; - next.C = node.C; - next.L = left; - left.U = next; - if (next !== right) { - parent = next.U; - next.U = node.U; - node = next.R; - parent.L = node; - next.R = right; - right.U = next; - } else { - next.U = parent; - parent = next; - node = next.R; - } - } else { - red = node.C; - node = next; - } - if (node) node.U = parent; - if (red) return; - if (node && node.C) { - node.C = false; - return; - } - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - sibling = parent.R; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.R || !sibling.R.C) { - sibling.L.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - node = this._; - break; - } - } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateRight(this, parent); - sibling = parent.L; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.L || !sibling.L.C) { - sibling.R.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, sibling); - sibling = parent.L; - } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - d3_geom_voronoiRedBlackRotateRight(this, parent); - node = this._; - break; - } - } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); - if (node) node.C = false; - } - }; - function d3_geom_voronoiRedBlackRotateLeft(tree, node) { - var p = node, q = node.R, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; - } - function d3_geom_voronoiRedBlackRotateRight(tree, node) { - var p = node, q = node.L, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; - } - function d3_geom_voronoiRedBlackFirst(node) { - while (node.L) node = node.L; - return node; - } - function d3_geom_voronoi(sites, bbox) { - var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; - d3_geom_voronoiEdges = []; - d3_geom_voronoiCells = new Array(sites.length); - d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); - d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); - while (true) { - circle = d3_geom_voronoiFirstCircle; - if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { - if (site.x !== x0 || site.y !== y0) { - d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); - d3_geom_voronoiAddBeach(site); - x0 = site.x, y0 = site.y; - } - site = sites.pop(); - } else if (circle) { - d3_geom_voronoiRemoveBeach(circle.arc); - } else { - break; - } - } - if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); - var diagram = { - cells: d3_geom_voronoiCells, - edges: d3_geom_voronoiEdges - }; - d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; - return diagram; - } - function d3_geom_voronoiVertexOrder(a, b) { - return b.y - a.y || b.x - a.x; - } - d3.geom.voronoi = function(points) { - var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; - if (points) return voronoi(points); - function voronoi(data) { - var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; - d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { - var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { - var s = e.start(); - return [ s.x, s.y ]; - }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; - polygon.point = data[i]; - }); - return polygons; - } - function sites(data) { - return data.map(function(d, i) { - return { - x: Math.round(fx(d, i) / ε) * ε, - y: Math.round(fy(d, i) / ε) * ε, - i: i - }; - }); - } - voronoi.links = function(data) { - return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { - return edge.l && edge.r; - }).map(function(edge) { - return { - source: data[edge.l.i], - target: data[edge.r.i] - }; - }); - }; - voronoi.triangles = function(data) { - var triangles = []; - d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { - var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; - while (++j < m) { - e0 = e1; - s0 = s1; - e1 = edges[j].edge; - s1 = e1.l === site ? e1.r : e1.l; - if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { - triangles.push([ data[i], data[s0.i], data[s1.i] ]); - } - } - }); - return triangles; - }; - voronoi.x = function(_) { - return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; - }; - voronoi.y = function(_) { - return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; - }; - voronoi.clipExtent = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; - clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; - return voronoi; - }; - voronoi.size = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; - return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); - }; - return voronoi; - }; - var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; - function d3_geom_voronoiTriangleArea(a, b, c) { - return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); - } - d3.geom.delaunay = function(vertices) { - return d3.geom.voronoi().triangles(vertices); - }; - d3.geom.quadtree = function(points, x1, y1, x2, y2) { - var x = d3_geom_pointX, y = d3_geom_pointY, compat; - if (compat = arguments.length) { - x = d3_geom_quadtreeCompatX; - y = d3_geom_quadtreeCompatY; - if (compat === 3) { - y2 = y1; - x2 = x1; - y1 = x1 = 0; - } - return quadtree(points); - } - function quadtree(data) { - var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; - if (x1 != null) { - x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; - } else { - x2_ = y2_ = -(x1_ = y1_ = Infinity); - xs = [], ys = []; - n = data.length; - if (compat) for (i = 0; i < n; ++i) { - d = data[i]; - if (d.x < x1_) x1_ = d.x; - if (d.y < y1_) y1_ = d.y; - if (d.x > x2_) x2_ = d.x; - if (d.y > y2_) y2_ = d.y; - xs.push(d.x); - ys.push(d.y); - } else for (i = 0; i < n; ++i) { - var x_ = +fx(d = data[i], i), y_ = +fy(d, i); - if (x_ < x1_) x1_ = x_; - if (y_ < y1_) y1_ = y_; - if (x_ > x2_) x2_ = x_; - if (y_ > y2_) y2_ = y_; - xs.push(x_); - ys.push(y_); - } - } - var dx = x2_ - x1_, dy = y2_ - y1_; - if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; - function insert(n, d, x, y, x1, y1, x2, y2) { - if (isNaN(x) || isNaN(y)) return; - if (n.leaf) { - var nx = n.x, ny = n.y; - if (nx != null) { - if (abs(nx - x) + abs(ny - y) < .01) { - insertChild(n, d, x, y, x1, y1, x2, y2); - } else { - var nPoint = n.point; - n.x = n.y = n.point = null; - insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } else { - n.x = x, n.y = y, n.point = d; - } - } else { - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } - function insertChild(n, d, x, y, x1, y1, x2, y2) { - var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; - n.leaf = false; - n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); - if (right) x1 = xm; else x2 = xm; - if (below) y1 = ym; else y2 = ym; - insert(n, d, x, y, x1, y1, x2, y2); - } - var root = d3_geom_quadtreeNode(); - root.add = function(d) { - insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); - }; - root.visit = function(f) { - d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); - }; - root.find = function(point) { - return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); - }; - i = -1; - if (x1 == null) { - while (++i < n) { - insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); - } - --i; - } else data.forEach(root.add); - xs = ys = data = d = null; - return root; - } - quadtree.x = function(_) { - return arguments.length ? (x = _, quadtree) : x; - }; - quadtree.y = function(_) { - return arguments.length ? (y = _, quadtree) : y; - }; - quadtree.extent = function(_) { - if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], - y2 = +_[1][1]; - return quadtree; - }; - quadtree.size = function(_) { - if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; - return quadtree; - }; - return quadtree; - }; - function d3_geom_quadtreeCompatX(d) { - return d.x; - } - function d3_geom_quadtreeCompatY(d) { - return d.y; - } - function d3_geom_quadtreeNode() { - return { - leaf: true, - nodes: [], - point: null, - x: null, - y: null - }; - } - function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { - if (!f(node, x1, y1, x2, y2)) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; - if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); - if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); - if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); - if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); - } - } - function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { - var minDistance2 = Infinity, closestPoint; - (function find(node, x1, y1, x2, y2) { - if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; - if (point = node.point) { - var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; - if (distance2 < minDistance2) { - var distance = Math.sqrt(minDistance2 = distance2); - x0 = x - distance, y0 = y - distance; - x3 = x + distance, y3 = y + distance; - closestPoint = point; - } - } - var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; - for (var i = below << 1 | right, j = i + 4; i < j; ++i) { - if (node = children[i & 3]) switch (i & 3) { - case 0: - find(node, x1, y1, xm, ym); - break; - - case 1: - find(node, xm, y1, x2, ym); - break; - - case 2: - find(node, x1, ym, xm, y2); - break; - - case 3: - find(node, xm, ym, x2, y2); - break; - } - } - })(root, x0, y0, x3, y3); - return closestPoint; - } - d3.interpolateRgb = d3_interpolateRgb; - function d3_interpolateRgb(a, b) { - a = d3.rgb(a); - b = d3.rgb(b); - var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; - return function(t) { - return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); - }; - } - d3.interpolateObject = d3_interpolateObject; - function d3_interpolateObject(a, b) { - var i = {}, c = {}, k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolate(a[k], b[k]); - } else { - c[k] = a[k]; - } - } - for (k in b) { - if (!(k in a)) { - c[k] = b[k]; - } - } - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; - } - d3.interpolateNumber = d3_interpolateNumber; - function d3_interpolateNumber(a, b) { - a = +a, b = +b; - return function(t) { - return a * (1 - t) + b * t; - }; - } - d3.interpolateString = d3_interpolateString; - function d3_interpolateString(a, b) { - var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; - a = a + "", b = b + ""; - while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { - if ((bs = bm.index) > bi) { - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { - if (s[i]) s[i] += bm; else s[++i] = bm; - } else { - s[++i] = null; - q.push({ - i: i, - x: d3_interpolateNumber(am, bm) - }); - } - bi = d3_interpolate_numberB.lastIndex; - } - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { - return b(t) + ""; - }) : function() { - return b; - } : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); - } - var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); - d3.interpolate = d3_interpolate; - function d3_interpolate(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; - return f; - } - d3.interpolators = [ function(a, b) { - var t = typeof b; - return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); - } ]; - d3.interpolateArray = d3_interpolateArray; - function d3_interpolateArray(a, b) { - var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; - for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); - for (;i < na; ++i) c[i] = a[i]; - for (;i < nb; ++i) c[i] = b[i]; - return function(t) { - for (i = 0; i < n0; ++i) c[i] = x[i](t); - return c; - }; - } - var d3_ease_default = function() { - return d3_identity; - }; - var d3_ease = d3.map({ - linear: d3_ease_default, - poly: d3_ease_poly, - quad: function() { - return d3_ease_quad; - }, - cubic: function() { - return d3_ease_cubic; - }, - sin: function() { - return d3_ease_sin; - }, - exp: function() { - return d3_ease_exp; - }, - circle: function() { - return d3_ease_circle; - }, - elastic: d3_ease_elastic, - back: d3_ease_back, - bounce: function() { - return d3_ease_bounce; - } - }); - var d3_ease_mode = d3.map({ - "in": d3_identity, - out: d3_ease_reverse, - "in-out": d3_ease_reflect, - "out-in": function(f) { - return d3_ease_reflect(d3_ease_reverse(f)); - } - }); - d3.ease = function(name) { - var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; - t = d3_ease.get(t) || d3_ease_default; - m = d3_ease_mode.get(m) || d3_identity; - return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); - }; - function d3_ease_clamp(f) { - return function(t) { - return t <= 0 ? 0 : t >= 1 ? 1 : f(t); - }; - } - function d3_ease_reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; - } - function d3_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); - }; - } - function d3_ease_quad(t) { - return t * t; - } - function d3_ease_cubic(t) { - return t * t * t; - } - function d3_ease_cubicInOut(t) { - if (t <= 0) return 0; - if (t >= 1) return 1; - var t2 = t * t, t3 = t2 * t; - return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); - } - function d3_ease_poly(e) { - return function(t) { - return Math.pow(t, e); - }; - } - function d3_ease_sin(t) { - return 1 - Math.cos(t * halfπ); - } - function d3_ease_exp(t) { - return Math.pow(2, 10 * (t - 1)); - } - function d3_ease_circle(t) { - return 1 - Math.sqrt(1 - t * t); - } - function d3_ease_elastic(a, p) { - var s; - if (arguments.length < 2) p = .45; - if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; - return function(t) { - return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); - }; - } - function d3_ease_back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); - }; - } - function d3_ease_bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; - } - d3.interpolateHcl = d3_interpolateHcl; - function d3_interpolateHcl(a, b) { - a = d3.hcl(a); - b = d3.hcl(b); - var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; - if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; - }; - } - d3.interpolateHsl = d3_interpolateHsl; - function d3_interpolateHsl(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; - if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; - }; - } - d3.interpolateLab = d3_interpolateLab; - function d3_interpolateLab(a, b) { - a = d3.lab(a); - b = d3.lab(b); - var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; - return function(t) { - return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; - }; - } - d3.interpolateRound = d3_interpolateRound; - function d3_interpolateRound(a, b) { - b -= a; - return function(t) { - return Math.round(a + b * t); - }; - } - d3.transform = function(string) { - var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); - return (d3.transform = function(string) { - if (string != null) { - g.setAttribute("transform", string); - var t = g.transform.baseVal.consolidate(); - } - return new d3_transform(t ? t.matrix : d3_transformIdentity); - })(string); - }; - function d3_transform(m) { - var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; - if (r0[0] * r1[1] < r1[0] * r0[1]) { - r0[0] *= -1; - r0[1] *= -1; - kx *= -1; - kz *= -1; - } - this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; - this.translate = [ m.e, m.f ]; - this.scale = [ kx, ky ]; - this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; - } - d3_transform.prototype.toString = function() { - return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; - }; - function d3_transformDot(a, b) { - return a[0] * b[0] + a[1] * b[1]; - } - function d3_transformNormalize(a) { - var k = Math.sqrt(d3_transformDot(a, a)); - if (k) { - a[0] /= k; - a[1] /= k; - } - return k; - } - function d3_transformCombine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; - } - var d3_transformIdentity = { - a: 1, - b: 0, - c: 0, - d: 1, - e: 0, - f: 0 - }; - d3.interpolateTransform = d3_interpolateTransform; - function d3_interpolateTransformPop(s) { - return s.length ? s.pop() + "," : ""; - } - function d3_interpolateTranslate(ta, tb, s, q) { - if (ta[0] !== tb[0] || ta[1] !== tb[1]) { - var i = s.push("translate(", null, ",", null, ")"); - q.push({ - i: i - 4, - x: d3_interpolateNumber(ta[0], tb[0]) - }, { - i: i - 2, - x: d3_interpolateNumber(ta[1], tb[1]) - }); - } else if (tb[0] || tb[1]) { - s.push("translate(" + tb + ")"); - } - } - function d3_interpolateRotate(ra, rb, s, q) { - if (ra !== rb) { - if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; - q.push({ - i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, - x: d3_interpolateNumber(ra, rb) - }); - } else if (rb) { - s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); - } - } - function d3_interpolateSkew(wa, wb, s, q) { - if (wa !== wb) { - q.push({ - i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, - x: d3_interpolateNumber(wa, wb) - }); - } else if (wb) { - s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); - } - } - function d3_interpolateScale(ka, kb, s, q) { - if (ka[0] !== kb[0] || ka[1] !== kb[1]) { - var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); - q.push({ - i: i - 4, - x: d3_interpolateNumber(ka[0], kb[0]) - }, { - i: i - 2, - x: d3_interpolateNumber(ka[1], kb[1]) - }); - } else if (kb[0] !== 1 || kb[1] !== 1) { - s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); - } - } - function d3_interpolateTransform(a, b) { - var s = [], q = []; - a = d3.transform(a), b = d3.transform(b); - d3_interpolateTranslate(a.translate, b.translate, s, q); - d3_interpolateRotate(a.rotate, b.rotate, s, q); - d3_interpolateSkew(a.skew, b.skew, s, q); - d3_interpolateScale(a.scale, b.scale, s, q); - a = b = null; - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - } - function d3_uninterpolateNumber(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return (x - a) / b; - }; - } - function d3_uninterpolateClamp(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return Math.max(0, Math.min(1, (x - a) / b)); - }; - } - d3.layout = {}; - d3.layout.bundle = function() { - return function(links) { - var paths = [], i = -1, n = links.length; - while (++i < n) paths.push(d3_layout_bundlePath(links[i])); - return paths; - }; - }; - function d3_layout_bundlePath(link) { - var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; - while (start !== lca) { - start = start.parent; - points.push(start); - } - var k = points.length; - while (end !== lca) { - points.splice(k, 0, end); - end = end.parent; - } - return points; - } - function d3_layout_bundleAncestors(node) { - var ancestors = [], parent = node.parent; - while (parent != null) { - ancestors.push(node); - node = parent; - parent = parent.parent; - } - ancestors.push(node); - return ancestors; - } - function d3_layout_bundleLeastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; - while (aNode === bNode) { - sharedNode = aNode; - aNode = aNodes.pop(); - bNode = bNodes.pop(); - } - return sharedNode; - } - d3.layout.chord = function() { - var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; - function relayout() { - var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; - chords = []; - groups = []; - k = 0, i = -1; - while (++i < n) { - x = 0, j = -1; - while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(d3.range(n)); - k += x; - } - if (sortGroups) { - groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); - } - if (sortSubgroups) { - subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); - } - k = (τ - padding * n) / k; - x = 0, i = -1; - while (++i < n) { - x0 = x, j = -1; - while (++j < n) { - var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; - subgroups[di + "-" + dj] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: groupSums[di] - }; - x += padding; - } - i = -1; - while (++i < n) { - j = i - 1; - while (++j < n) { - var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; - if (source.value || target.value) { - chords.push(source.value < target.value ? { - source: target, - target: source - } : { - source: source, - target: target - }); - } - } - } - if (sortChords) resort(); - } - function resort() { - chords.sort(function(a, b) { - return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); - }); - } - chord.matrix = function(x) { - if (!arguments.length) return matrix; - n = (matrix = x) && matrix.length; - chords = groups = null; - return chord; - }; - chord.padding = function(x) { - if (!arguments.length) return padding; - padding = x; - chords = groups = null; - return chord; - }; - chord.sortGroups = function(x) { - if (!arguments.length) return sortGroups; - sortGroups = x; - chords = groups = null; - return chord; - }; - chord.sortSubgroups = function(x) { - if (!arguments.length) return sortSubgroups; - sortSubgroups = x; - chords = null; - return chord; - }; - chord.sortChords = function(x) { - if (!arguments.length) return sortChords; - sortChords = x; - if (chords) resort(); - return chord; - }; - chord.chords = function() { - if (!chords) relayout(); - return chords; - }; - chord.groups = function() { - if (!groups) relayout(); - return groups; - }; - return chord; - }; - d3.layout.force = function() { - var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; - function repulse(node) { - return function(quad, x1, _, x2) { - if (quad.point !== node) { - var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; - if (dw * dw / theta2 < dn) { - if (dn < chargeDistance2) { - var k = quad.charge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - return true; - } - if (quad.point && dn && dn < chargeDistance2) { - var k = quad.pointCharge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - } - return !quad.charge; - }; - } - force.tick = function() { - if ((alpha *= .99) < .005) { - timer = null; - event.end({ - type: "end", - alpha: alpha = 0 - }); - return true; - } - var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; - for (i = 0; i < m; ++i) { - o = links[i]; - s = o.source; - t = o.target; - x = t.x - s.x; - y = t.y - s.y; - if (l = x * x + y * y) { - l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; - x *= l; - y *= l; - t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); - t.y -= y * k; - s.x += x * (k = 1 - k); - s.y += y * k; - } - } - if (k = alpha * gravity) { - x = size[0] / 2; - y = size[1] / 2; - i = -1; - if (k) while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * k; - o.y += (y - o.y) * k; - } - } - if (charge) { - d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); - i = -1; - while (++i < n) { - if (!(o = nodes[i]).fixed) { - q.visit(repulse(o)); - } - } - } - i = -1; - while (++i < n) { - o = nodes[i]; - if (o.fixed) { - o.x = o.px; - o.y = o.py; - } else { - o.x -= (o.px - (o.px = o.x)) * friction; - o.y -= (o.py - (o.py = o.y)) * friction; - } - } - event.tick({ - type: "tick", - alpha: alpha - }); - }; - force.nodes = function(x) { - if (!arguments.length) return nodes; - nodes = x; - return force; - }; - force.links = function(x) { - if (!arguments.length) return links; - links = x; - return force; - }; - force.size = function(x) { - if (!arguments.length) return size; - size = x; - return force; - }; - force.linkDistance = function(x) { - if (!arguments.length) return linkDistance; - linkDistance = typeof x === "function" ? x : +x; - return force; - }; - force.distance = force.linkDistance; - force.linkStrength = function(x) { - if (!arguments.length) return linkStrength; - linkStrength = typeof x === "function" ? x : +x; - return force; - }; - force.friction = function(x) { - if (!arguments.length) return friction; - friction = +x; - return force; - }; - force.charge = function(x) { - if (!arguments.length) return charge; - charge = typeof x === "function" ? x : +x; - return force; - }; - force.chargeDistance = function(x) { - if (!arguments.length) return Math.sqrt(chargeDistance2); - chargeDistance2 = x * x; - return force; - }; - force.gravity = function(x) { - if (!arguments.length) return gravity; - gravity = +x; - return force; - }; - force.theta = function(x) { - if (!arguments.length) return Math.sqrt(theta2); - theta2 = x * x; - return force; - }; - force.alpha = function(x) { - if (!arguments.length) return alpha; - x = +x; - if (alpha) { - if (x > 0) { - alpha = x; - } else { - timer.c = null, timer.t = NaN, timer = null; - event.end({ - type: "end", - alpha: alpha = 0 - }); - } - } else if (x > 0) { - event.start({ - type: "start", - alpha: alpha = x - }); - timer = d3_timer(force.tick); - } - return force; - }; - force.start = function() { - var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; - for (i = 0; i < n; ++i) { - (o = nodes[i]).index = i; - o.weight = 0; - } - for (i = 0; i < m; ++i) { - o = links[i]; - if (typeof o.source == "number") o.source = nodes[o.source]; - if (typeof o.target == "number") o.target = nodes[o.target]; - ++o.source.weight; - ++o.target.weight; - } - for (i = 0; i < n; ++i) { - o = nodes[i]; - if (isNaN(o.x)) o.x = position("x", w); - if (isNaN(o.y)) o.y = position("y", h); - if (isNaN(o.px)) o.px = o.x; - if (isNaN(o.py)) o.py = o.y; - } - distances = []; - if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; - strengths = []; - if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; - charges = []; - if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; - function position(dimension, size) { - if (!neighbors) { - neighbors = new Array(n); - for (j = 0; j < n; ++j) { - neighbors[j] = []; - } - for (j = 0; j < m; ++j) { - var o = links[j]; - neighbors[o.source.index].push(o.target); - neighbors[o.target.index].push(o.source); - } - } - var candidates = neighbors[i], j = -1, l = candidates.length, x; - while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; - return Math.random() * size; - } - return force.resume(); - }; - force.resume = function() { - return force.alpha(.1); - }; - force.stop = function() { - return force.alpha(0); - }; - force.drag = function() { - if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); - if (!arguments.length) return drag; - this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); - }; - function dragmove(d) { - d.px = d3.event.x, d.py = d3.event.y; - force.resume(); - } - return d3.rebind(force, event, "on"); - }; - function d3_layout_forceDragstart(d) { - d.fixed |= 2; - } - function d3_layout_forceDragend(d) { - d.fixed &= ~6; - } - function d3_layout_forceMouseover(d) { - d.fixed |= 4; - d.px = d.x, d.py = d.y; - } - function d3_layout_forceMouseout(d) { - d.fixed &= ~4; - } - function d3_layout_forceAccumulate(quad, alpha, charges) { - var cx = 0, cy = 0; - quad.charge = 0; - if (!quad.leaf) { - var nodes = quad.nodes, n = nodes.length, i = -1, c; - while (++i < n) { - c = nodes[i]; - if (c == null) continue; - d3_layout_forceAccumulate(c, alpha, charges); - quad.charge += c.charge; - cx += c.charge * c.cx; - cy += c.charge * c.cy; - } - } - if (quad.point) { - if (!quad.leaf) { - quad.point.x += Math.random() - .5; - quad.point.y += Math.random() - .5; - } - var k = alpha * charges[quad.point.index]; - quad.charge += quad.pointCharge = k; - cx += k * quad.point.x; - cy += k * quad.point.y; - } - quad.cx = cx / quad.charge; - quad.cy = cy / quad.charge; - } - var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; - d3.layout.hierarchy = function() { - var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; - function hierarchy(root) { - var stack = [ root ], nodes = [], node; - root.depth = 0; - while ((node = stack.pop()) != null) { - nodes.push(node); - if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { - var n, childs, child; - while (--n >= 0) { - stack.push(child = childs[n]); - child.parent = node; - child.depth = node.depth + 1; - } - if (value) node.value = 0; - node.children = childs; - } else { - if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; - delete node.children; - } - } - d3_layout_hierarchyVisitAfter(root, function(node) { - var childs, parent; - if (sort && (childs = node.children)) childs.sort(sort); - if (value && (parent = node.parent)) parent.value += node.value; - }); - return nodes; - } - hierarchy.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return hierarchy; - }; - hierarchy.children = function(x) { - if (!arguments.length) return children; - children = x; - return hierarchy; - }; - hierarchy.value = function(x) { - if (!arguments.length) return value; - value = x; - return hierarchy; - }; - hierarchy.revalue = function(root) { - if (value) { - d3_layout_hierarchyVisitBefore(root, function(node) { - if (node.children) node.value = 0; - }); - d3_layout_hierarchyVisitAfter(root, function(node) { - var parent; - if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; - if (parent = node.parent) parent.value += node.value; - }); - } - return root; - }; - return hierarchy; - }; - function d3_layout_hierarchyRebind(object, hierarchy) { - d3.rebind(object, hierarchy, "sort", "children", "value"); - object.nodes = object; - object.links = d3_layout_hierarchyLinks; - return object; - } - function d3_layout_hierarchyVisitBefore(node, callback) { - var nodes = [ node ]; - while ((node = nodes.pop()) != null) { - callback(node); - if ((children = node.children) && (n = children.length)) { - var n, children; - while (--n >= 0) nodes.push(children[n]); - } - } - } - function d3_layout_hierarchyVisitAfter(node, callback) { - var nodes = [ node ], nodes2 = []; - while ((node = nodes.pop()) != null) { - nodes2.push(node); - if ((children = node.children) && (n = children.length)) { - var i = -1, n, children; - while (++i < n) nodes.push(children[i]); - } - } - while ((node = nodes2.pop()) != null) { - callback(node); - } - } - function d3_layout_hierarchyChildren(d) { - return d.children; - } - function d3_layout_hierarchyValue(d) { - return d.value; - } - function d3_layout_hierarchySort(a, b) { - return b.value - a.value; - } - function d3_layout_hierarchyLinks(nodes) { - return d3.merge(nodes.map(function(parent) { - return (parent.children || []).map(function(child) { - return { - source: parent, - target: child - }; - }); - })); - } - d3.layout.partition = function() { - var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; - function position(node, x, dx, dy) { - var children = node.children; - node.x = x; - node.y = node.depth * dy; - node.dx = dx; - node.dy = dy; - if (children && (n = children.length)) { - var i = -1, n, c, d; - dx = node.value ? dx / node.value : 0; - while (++i < n) { - position(c = children[i], x, d = c.value * dx, dy); - x += d; - } - } - } - function depth(node) { - var children = node.children, d = 0; - if (children && (n = children.length)) { - var i = -1, n; - while (++i < n) d = Math.max(d, depth(children[i])); - } - return 1 + d; - } - function partition(d, i) { - var nodes = hierarchy.call(this, d, i); - position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); - return nodes; - } - partition.size = function(x) { - if (!arguments.length) return size; - size = x; - return partition; - }; - return d3_layout_hierarchyRebind(partition, hierarchy); - }; - d3.layout.pie = function() { - var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; - function pie(data) { - var n = data.length, values = data.map(function(d, i) { - return +value.call(pie, d, i); - }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; - if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { - return values[j] - values[i]; - } : function(i, j) { - return sort(data[i], data[j]); - }); - index.forEach(function(i) { - arcs[i] = { - data: data[i], - value: v = values[i], - startAngle: a, - endAngle: a += v * k + pa, - padAngle: p - }; - }); - return arcs; - } - pie.value = function(_) { - if (!arguments.length) return value; - value = _; - return pie; - }; - pie.sort = function(_) { - if (!arguments.length) return sort; - sort = _; - return pie; - }; - pie.startAngle = function(_) { - if (!arguments.length) return startAngle; - startAngle = _; - return pie; - }; - pie.endAngle = function(_) { - if (!arguments.length) return endAngle; - endAngle = _; - return pie; - }; - pie.padAngle = function(_) { - if (!arguments.length) return padAngle; - padAngle = _; - return pie; - }; - return pie; - }; - var d3_layout_pieSortByValue = {}; - d3.layout.stack = function() { - var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; - function stack(data, index) { - if (!(n = data.length)) return data; - var series = data.map(function(d, i) { - return values.call(stack, d, i); - }); - var points = series.map(function(d) { - return d.map(function(v, i) { - return [ x.call(stack, v, i), y.call(stack, v, i) ]; - }); - }); - var orders = order.call(stack, points, index); - series = d3.permute(series, orders); - points = d3.permute(points, orders); - var offsets = offset.call(stack, points, index); - var m = series[0].length, n, i, j, o; - for (j = 0; j < m; ++j) { - out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); - for (i = 1; i < n; ++i) { - out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); - } - } - return data; - } - stack.values = function(x) { - if (!arguments.length) return values; - values = x; - return stack; - }; - stack.order = function(x) { - if (!arguments.length) return order; - order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; - return stack; - }; - stack.offset = function(x) { - if (!arguments.length) return offset; - offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; - return stack; - }; - stack.x = function(z) { - if (!arguments.length) return x; - x = z; - return stack; - }; - stack.y = function(z) { - if (!arguments.length) return y; - y = z; - return stack; - }; - stack.out = function(z) { - if (!arguments.length) return out; - out = z; - return stack; - }; - return stack; - }; - function d3_layout_stackX(d) { - return d.x; - } - function d3_layout_stackY(d) { - return d.y; - } - function d3_layout_stackOut(d, y0, y) { - d.y0 = y0; - d.y = y; - } - var d3_layout_stackOrders = d3.map({ - "inside-out": function(data) { - var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { - return max[a] - max[b]; - }), top = 0, bottom = 0, tops = [], bottoms = []; - for (i = 0; i < n; ++i) { - j = index[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - return bottoms.reverse().concat(tops); - }, - reverse: function(data) { - return d3.range(data.length).reverse(); - }, - "default": d3_layout_stackOrderDefault - }); - var d3_layout_stackOffsets = d3.map({ - silhouette: function(data) { - var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o > max) max = o; - sums.push(o); - } - for (j = 0; j < m; ++j) { - y0[j] = (max - sums[j]) / 2; - } - return y0; - }, - wiggle: function(data) { - var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; - y0[0] = o = o0 = 0; - for (j = 1; j < m; ++j) { - for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; - for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { - for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { - s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; - } - s2 += s3 * data[i][j][1]; - } - y0[j] = o -= s1 ? s2 / s1 * dx : 0; - if (o < o0) o0 = o; - } - for (j = 0; j < m; ++j) y0[j] -= o0; - return y0; - }, - expand: function(data) { - var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; - } - for (j = 0; j < m; ++j) y0[j] = 0; - return y0; - }, - zero: d3_layout_stackOffsetZero - }); - function d3_layout_stackOrderDefault(data) { - return d3.range(data.length); - } - function d3_layout_stackOffsetZero(data) { - var j = -1, m = data[0].length, y0 = []; - while (++j < m) y0[j] = 0; - return y0; - } - function d3_layout_stackMaxIndex(array) { - var i = 1, j = 0, v = array[0][1], k, n = array.length; - for (;i < n; ++i) { - if ((k = array[i][1]) > v) { - j = i; - v = k; - } - } - return j; - } - function d3_layout_stackReduceSum(d) { - return d.reduce(d3_layout_stackSum, 0); - } - function d3_layout_stackSum(p, d) { - return p + d[1]; - } - d3.layout.histogram = function() { - var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; - function histogram(data, i) { - var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; - while (++i < m) { - bin = bins[i] = []; - bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); - bin.y = 0; - } - if (m > 0) { - i = -1; - while (++i < n) { - x = values[i]; - if (x >= range[0] && x <= range[1]) { - bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; - bin.y += k; - bin.push(data[i]); - } - } - } - return bins; - } - histogram.value = function(x) { - if (!arguments.length) return valuer; - valuer = x; - return histogram; - }; - histogram.range = function(x) { - if (!arguments.length) return ranger; - ranger = d3_functor(x); - return histogram; - }; - histogram.bins = function(x) { - if (!arguments.length) return binner; - binner = typeof x === "number" ? function(range) { - return d3_layout_histogramBinFixed(range, x); - } : d3_functor(x); - return histogram; - }; - histogram.frequency = function(x) { - if (!arguments.length) return frequency; - frequency = !!x; - return histogram; - }; - return histogram; - }; - function d3_layout_histogramBinSturges(range, values) { - return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); - } - function d3_layout_histogramBinFixed(range, n) { - var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; - while (++x <= n) f[x] = m * x + b; - return f; - } - function d3_layout_histogramRange(values) { - return [ d3.min(values), d3.max(values) ]; - } - d3.layout.pack = function() { - var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; - function pack(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { - return radius; - }; - root.x = root.y = 0; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r = +r(d.value); - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - if (padding) { - var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r += dr; - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r -= dr; - }); - } - d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); - return nodes; - } - pack.size = function(_) { - if (!arguments.length) return size; - size = _; - return pack; - }; - pack.radius = function(_) { - if (!arguments.length) return radius; - radius = _ == null || typeof _ === "function" ? _ : +_; - return pack; - }; - pack.padding = function(_) { - if (!arguments.length) return padding; - padding = +_; - return pack; - }; - return d3_layout_hierarchyRebind(pack, hierarchy); - }; - function d3_layout_packSort(a, b) { - return a.value - b.value; - } - function d3_layout_packInsert(a, b) { - var c = a._pack_next; - a._pack_next = b; - b._pack_prev = a; - b._pack_next = c; - c._pack_prev = b; - } - function d3_layout_packSplice(a, b) { - a._pack_next = b; - b._pack_prev = a; - } - function d3_layout_packIntersects(a, b) { - var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; - return .999 * dr * dr > dx * dx + dy * dy; - } - function d3_layout_packSiblings(node) { - if (!(nodes = node.children) || !(n = nodes.length)) return; - var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; - function bound(node) { - xMin = Math.min(node.x - node.r, xMin); - xMax = Math.max(node.x + node.r, xMax); - yMin = Math.min(node.y - node.r, yMin); - yMax = Math.max(node.y + node.r, yMax); - } - nodes.forEach(d3_layout_packLink); - a = nodes[0]; - a.x = -a.r; - a.y = 0; - bound(a); - if (n > 1) { - b = nodes[1]; - b.x = b.r; - b.y = 0; - bound(b); - if (n > 2) { - c = nodes[2]; - d3_layout_packPlace(a, b, c); - bound(c); - d3_layout_packInsert(a, c); - a._pack_prev = c; - d3_layout_packInsert(c, b); - b = a._pack_next; - for (i = 3; i < n; i++) { - d3_layout_packPlace(a, b, c = nodes[i]); - var isect = 0, s1 = 1, s2 = 1; - for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { - if (d3_layout_packIntersects(j, c)) { - isect = 1; - break; - } - } - if (isect == 1) { - for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { - if (d3_layout_packIntersects(k, c)) { - break; - } - } - } - if (isect) { - if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); - i--; - } else { - d3_layout_packInsert(a, c); - b = c; - bound(c); - } - } - } - } - var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; - for (i = 0; i < n; i++) { - c = nodes[i]; - c.x -= cx; - c.y -= cy; - cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); - } - node.r = cr; - nodes.forEach(d3_layout_packUnlink); - } - function d3_layout_packLink(node) { - node._pack_next = node._pack_prev = node; - } - function d3_layout_packUnlink(node) { - delete node._pack_next; - delete node._pack_prev; - } - function d3_layout_packTransform(node, x, y, k) { - var children = node.children; - node.x = x += k * node.x; - node.y = y += k * node.y; - node.r *= k; - if (children) { - var i = -1, n = children.length; - while (++i < n) d3_layout_packTransform(children[i], x, y, k); - } - } - function d3_layout_packPlace(a, b, c) { - var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; - if (db && (dx || dy)) { - var da = b.r + c.r, dc = dx * dx + dy * dy; - da *= da; - db *= db; - var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = a.x + x * dx + y * dy; - c.y = a.y + x * dy - y * dx; - } else { - c.x = a.x + db; - c.y = a.y; - } - } - d3.layout.tree = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; - function tree(d, i) { - var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); - d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; - d3_layout_hierarchyVisitBefore(root1, secondWalk); - if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { - var left = root0, right = root0, bottom = root0; - d3_layout_hierarchyVisitBefore(root0, function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); - d3_layout_hierarchyVisitBefore(root0, function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } - return nodes; - } - function wrapTree(root0) { - var root1 = { - A: null, - children: [ root0 ] - }, queue = [ root1 ], node1; - while ((node1 = queue.pop()) != null) { - for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { - queue.push((children[i] = child = { - _: children[i], - parent: node1, - children: (child = children[i].children) && child.slice() || [], - A: null, - a: null, - z: 0, - m: 0, - c: 0, - s: 0, - t: null, - i: i - }).a = child); - } - } - return root1.children[0]; - } - function firstWalk(v) { - var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; - if (children.length) { - d3_layout_treeShift(v); - var midpoint = (children[0].z + children[children.length - 1].z) / 2; - if (w) { - v.z = w.z + separation(v._, w._); - v.m = v.z - midpoint; - } else { - v.z = midpoint; - } - } else if (w) { - v.z = w.z + separation(v._, w._); - } - v.parent.A = apportion(v, w, v.parent.A || siblings[0]); - } - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } - function apportion(v, w, ancestor) { - if (w) { - var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; - while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { - vom = d3_layout_treeLeft(vom); - vop = d3_layout_treeRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !d3_layout_treeRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !d3_layout_treeLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } - } - return ancestor; - } - function sizeNode(node) { - node.x *= size[0]; - node.y = node.depth * size[1]; - } - tree.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return tree; - }; - tree.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null ? sizeNode : null; - return tree; - }; - tree.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) == null ? null : sizeNode; - return tree; - }; - return d3_layout_hierarchyRebind(tree, hierarchy); - }; - function d3_layout_treeSeparation(a, b) { - return a.parent == b.parent ? 1 : 2; - } - function d3_layout_treeLeft(v) { - var children = v.children; - return children.length ? children[0] : v.t; - } - function d3_layout_treeRight(v) { - var children = v.children, n; - return (n = children.length) ? children[n - 1] : v.t; - } - function d3_layout_treeMove(wm, wp, shift) { - var change = shift / (wp.i - wm.i); - wp.c -= change; - wp.s += shift; - wm.c += change; - wp.z += shift; - wp.m += shift; - } - function d3_layout_treeShift(v) { - var shift = 0, change = 0, children = v.children, i = children.length, w; - while (--i >= 0) { - w = children[i]; - w.z += shift; - w.m += shift; - shift += w.s + (change += w.c); - } - } - function d3_layout_treeAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; - } - d3.layout.cluster = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; - function cluster(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; - d3_layout_hierarchyVisitAfter(root, function(node) { - var children = node.children; - if (children && children.length) { - node.x = d3_layout_clusterX(children); - node.y = d3_layout_clusterY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); - var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; - d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { - node.x = (node.x - root.x) * size[0]; - node.y = (root.y - node.y) * size[1]; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; - }); - return nodes; - } - cluster.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return cluster; - }; - cluster.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null; - return cluster; - }; - cluster.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) != null; - return cluster; - }; - return d3_layout_hierarchyRebind(cluster, hierarchy); - }; - function d3_layout_clusterY(children) { - return 1 + d3.max(children, function(child) { - return child.y; - }); - } - function d3_layout_clusterX(children) { - return children.reduce(function(x, child) { - return x + child.x; - }, 0) / children.length; - } - function d3_layout_clusterLeft(node) { - var children = node.children; - return children && children.length ? d3_layout_clusterLeft(children[0]) : node; - } - function d3_layout_clusterRight(node) { - var children = node.children, n; - return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; - } - d3.layout.treemap = function() { - var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); - function scale(children, k) { - var i = -1, n = children.length, child, area; - while (++i < n) { - area = (child = children[i]).value * (k < 0 ? 0 : k); - child.area = isNaN(area) || area <= 0 ? 0 : area; - } - } - function squarify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while ((n = remaining.length) > 0) { - row.push(child = remaining[n - 1]); - row.area += child.area; - if (mode !== "squarify" || (score = worst(row, u)) <= best) { - remaining.pop(); - best = score; - } else { - row.area -= row.pop().area; - position(row, u, rect, false); - u = Math.min(rect.dx, rect.dy); - row.length = row.area = 0; - best = Infinity; - } - } - if (row.length) { - position(row, u, rect, true); - row.length = row.area = 0; - } - children.forEach(squarify); - } - } - function stickify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), remaining = children.slice(), child, row = []; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while (child = remaining.pop()) { - row.push(child); - row.area += child.area; - if (child.z != null) { - position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); - row.length = row.area = 0; - } - } - children.forEach(stickify); - } - } - function worst(row, u) { - var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; - while (++i < n) { - if (!(r = row[i].area)) continue; - if (r < rmin) rmin = r; - if (r > rmax) rmax = r; - } - s *= s; - u *= u; - return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; - } - function position(row, u, rect, flush) { - var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; - if (u == rect.dx) { - if (flush || v > rect.dy) v = rect.dy; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dy = v; - x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); - } - o.z = true; - o.dx += rect.x + rect.dx - x; - rect.y += v; - rect.dy -= v; - } else { - if (flush || v > rect.dx) v = rect.dx; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dx = v; - y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); - } - o.z = false; - o.dy += rect.y + rect.dy - y; - rect.x += v; - rect.dx -= v; - } - } - function treemap(d) { - var nodes = stickies || hierarchy(d), root = nodes[0]; - root.x = root.y = 0; - if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; - if (stickies) hierarchy.revalue(root); - scale([ root ], root.dx * root.dy / root.value); - (stickies ? stickify : squarify)(root); - if (sticky) stickies = nodes; - return nodes; - } - treemap.size = function(x) { - if (!arguments.length) return size; - size = x; - return treemap; - }; - treemap.padding = function(x) { - if (!arguments.length) return padding; - function padFunction(node) { - var p = x.call(treemap, node, node.depth); - return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); - } - function padConstant(node) { - return d3_layout_treemapPad(node, x); - } - var type; - pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], - padConstant) : padConstant; - return treemap; - }; - treemap.round = function(x) { - if (!arguments.length) return round != Number; - round = x ? Math.round : Number; - return treemap; - }; - treemap.sticky = function(x) { - if (!arguments.length) return sticky; - sticky = x; - stickies = null; - return treemap; - }; - treemap.ratio = function(x) { - if (!arguments.length) return ratio; - ratio = x; - return treemap; - }; - treemap.mode = function(x) { - if (!arguments.length) return mode; - mode = x + ""; - return treemap; - }; - return d3_layout_hierarchyRebind(treemap, hierarchy); - }; - function d3_layout_treemapPadNull(node) { - return { - x: node.x, - y: node.y, - dx: node.dx, - dy: node.dy - }; - } - function d3_layout_treemapPad(node, padding) { - var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; - if (dx < 0) { - x += dx / 2; - dx = 0; - } - if (dy < 0) { - y += dy / 2; - dy = 0; - } - return { - x: x, - y: y, - dx: dx, - dy: dy - }; - } - d3.random = { - normal: function(µ, σ) { - var n = arguments.length; - if (n < 2) σ = 1; - if (n < 1) µ = 0; - return function() { - var x, y, r; - do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); - }; - }, - logNormal: function() { - var random = d3.random.normal.apply(d3, arguments); - return function() { - return Math.exp(random()); - }; - }, - bates: function(m) { - var random = d3.random.irwinHall(m); - return function() { - return random() / m; - }; - }, - irwinHall: function(m) { - return function() { - for (var s = 0, j = 0; j < m; j++) s += Math.random(); - return s; - }; - } - }; - d3.scale = {}; - function d3_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; - } - function d3_scaleRange(scale) { - return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); - } - function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { - var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); - return function(x) { - return i(u(x)); - }; - } - function d3_scale_nice(domain, nice) { - var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; - if (x1 < x0) { - dx = i0, i0 = i1, i1 = dx; - dx = x0, x0 = x1, x1 = dx; - } - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - return domain; - } - function d3_scale_niceStep(step) { - return step ? { - floor: function(x) { - return Math.floor(x / step) * step; - }, - ceil: function(x) { - return Math.ceil(x / step) * step; - } - } : d3_scale_niceIdentity; - } - var d3_scale_niceIdentity = { - floor: d3_identity, - ceil: d3_identity - }; - function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { - var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; - if (domain[k] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); - } - while (++j <= k) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); - } - return function(x) { - var j = d3.bisect(domain, x, 1, k) - 1; - return i[j](u[j](x)); - }; - } - d3.scale.linear = function() { - return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); - }; - function d3_scale_linear(domain, range, interpolate, clamp) { - var output, input; - function rescale() { - var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; - output = linear(domain, range, uninterpolate, interpolate); - input = linear(range, domain, uninterpolate, d3_interpolate); - return scale; - } - function scale(x) { - return output(x); - } - scale.invert = function(y) { - return input(y); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3_interpolateRound); - }; - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); - }; - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - d3_scale_linearNice(domain, m); - return rescale(); - }; - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); - }; - return rescale(); - } - function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_scale_linearNice(domain, m) { - d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - return domain; - } - function d3_scale_linearTickRange(domain, m) { - if (m == null) m = 10; - var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; - if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; - extent[0] = Math.ceil(extent[0] / step) * step; - extent[1] = Math.floor(extent[1] / step) * step + step * .5; - extent[2] = step; - return extent; - } - function d3_scale_linearTicks(domain, m) { - return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); - } - function d3_scale_linearTickFormat(domain, m, format) { - var range = d3_scale_linearTickRange(domain, m); - if (format) { - var match = d3_format_re.exec(format); - match.shift(); - if (match[8] === "s") { - var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); - if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); - match[8] = "f"; - format = d3.format(match.join("")); - return function(d) { - return format(prefix.scale(d)) + prefix.symbol; - }; - } - if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); - format = match.join(""); - } else { - format = ",." + d3_scale_linearPrecision(range[2]) + "f"; - } - return d3.format(format); - } - var d3_scale_linearFormatSignificant = { - s: 1, - g: 1, - p: 1, - r: 1, - e: 1 - }; - function d3_scale_linearPrecision(value) { - return -Math.floor(Math.log(value) / Math.LN10 + .01); - } - function d3_scale_linearFormatPrecision(type, range) { - var p = d3_scale_linearPrecision(range[2]); - return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; - } - d3.scale.log = function() { - return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); - }; - function d3_scale_log(linear, base, positive, domain) { - function log(x) { - return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); - } - function pow(x) { - return positive ? Math.pow(base, x) : -Math.pow(base, -x); - } - function scale(x) { - return linear(log(x)); - } - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - positive = x[0] >= 0; - linear.domain((domain = x.map(Number)).map(log)); - return scale; - }; - scale.base = function(_) { - if (!arguments.length) return base; - base = +_; - linear.domain(domain.map(log)); - return scale; - }; - scale.nice = function() { - var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); - linear.domain(niced); - domain = niced.map(pow); - return scale; - }; - scale.ticks = function() { - var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; - if (isFinite(j - i)) { - if (positive) { - for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } else { - ticks.push(pow(i)); - for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); - } - for (i = 0; ticks[i] < u; i++) {} - for (j = ticks.length; ticks[j - 1] > v; j--) {} - ticks = ticks.slice(i, j); - } - return ticks; - }; - scale.tickFormat = function(n, format) { - if (!arguments.length) return d3_scale_logFormat; - if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); - var k = Math.max(1, base * n / scale.ticks().length); - return function(d) { - var i = d / pow(Math.round(log(d))); - if (i * base < base - .5) i *= base; - return i <= k ? format(d) : ""; - }; - }; - scale.copy = function() { - return d3_scale_log(linear.copy(), base, positive, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { - floor: function(x) { - return -Math.ceil(-x); - }, - ceil: function(x) { - return -Math.floor(-x); - } - }; - d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); - }; - function d3_scale_pow(linear, exponent, domain) { - var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); - function scale(x) { - return linear(powp(x)); - } - scale.invert = function(x) { - return powb(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - linear.domain((domain = x.map(Number)).map(powp)); - return scale; - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - return scale.domain(d3_scale_linearNice(domain, m)); - }; - scale.exponent = function(x) { - if (!arguments.length) return exponent; - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - linear.domain(domain.map(powp)); - return scale; - }; - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_scale_powPow(e) { - return function(x) { - return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); - }; - } - d3.scale.sqrt = function() { - return d3.scale.pow().exponent(.5); - }; - d3.scale.ordinal = function() { - return d3_scale_ordinal([], { - t: "range", - a: [ [] ] - }); - }; - function d3_scale_ordinal(domain, ranger) { - var index, range, rangeBand; - function scale(x) { - return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; - } - function steps(start, step) { - return d3.range(domain.length).map(function(i) { - return start + step * i; - }); - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = []; - index = new d3_Map(); - var i = -1, n = x.length, xi; - while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); - return scale[ranger.t].apply(scale, ranger.a); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = { - t: "range", - a: arguments - }; - return scale; - }; - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, - 0) : (stop - start) / (domain.length - 1 + padding); - range = steps(start + step * padding / 2, step); - rangeBand = 0; - ranger = { - t: "rangePoints", - a: arguments - }; - return scale; - }; - scale.rangeRoundPoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), - 0) : (stop - start) / (domain.length - 1 + padding) | 0; - range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); - rangeBand = 0; - ranger = { - t: "rangeRoundPoints", - a: arguments - }; - return scale; - }; - scale.rangeBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); - range = steps(start + step * outerPadding, step); - if (reverse) range.reverse(); - rangeBand = step * (1 - padding); - ranger = { - t: "rangeBands", - a: arguments - }; - return scale; - }; - scale.rangeRoundBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); - range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); - if (reverse) range.reverse(); - rangeBand = Math.round(step * (1 - padding)); - ranger = { - t: "rangeRoundBands", - a: arguments - }; - return scale; - }; - scale.rangeBand = function() { - return rangeBand; - }; - scale.rangeExtent = function() { - return d3_scaleExtent(ranger.a[0]); - }; - scale.copy = function() { - return d3_scale_ordinal(domain, ranger); - }; - return scale.domain(domain); - } - d3.scale.category10 = function() { - return d3.scale.ordinal().range(d3_category10); - }; - d3.scale.category20 = function() { - return d3.scale.ordinal().range(d3_category20); - }; - d3.scale.category20b = function() { - return d3.scale.ordinal().range(d3_category20b); - }; - d3.scale.category20c = function() { - return d3.scale.ordinal().range(d3_category20c); - }; - var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); - var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); - var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); - var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); - d3.scale.quantile = function() { - return d3_scale_quantile([], []); - }; - function d3_scale_quantile(domain, range) { - var thresholds; - function rescale() { - var k = 0, q = range.length; - thresholds = []; - while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); - return scale; - } - function scale(x) { - if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.quantiles = function() { - return thresholds; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; - }; - scale.copy = function() { - return d3_scale_quantile(domain, range); - }; - return rescale(); - } - d3.scale.quantize = function() { - return d3_scale_quantize(0, 1, [ 0, 1 ]); - }; - function d3_scale_quantize(x0, x1, range) { - var kx, i; - function scale(x) { - return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; - } - function rescale() { - kx = range.length / (x1 - x0); - i = range.length - 1; - return scale; - } - scale.domain = function(x) { - if (!arguments.length) return [ x0, x1 ]; - x0 = +x[0]; - x1 = +x[x.length - 1]; - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - y = y < 0 ? NaN : y / kx + x0; - return [ y, y + 1 / kx ]; - }; - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); - }; - return rescale(); - } - d3.scale.threshold = function() { - return d3_scale_threshold([ .5 ], [ 0, 1 ]); - }; - function d3_scale_threshold(domain, range) { - function scale(x) { - if (x <= x) return range[d3.bisect(domain, x)]; - } - scale.domain = function(_) { - if (!arguments.length) return domain; - domain = _; - return scale; - }; - scale.range = function(_) { - if (!arguments.length) return range; - range = _; - return scale; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return [ domain[y - 1], domain[y] ]; - }; - scale.copy = function() { - return d3_scale_threshold(domain, range); - }; - return scale; - } - d3.scale.identity = function() { - return d3_scale_identity([ 0, 1 ]); - }; - function d3_scale_identity(domain) { - function identity(x) { - return +x; - } - identity.invert = identity; - identity.domain = identity.range = function(x) { - if (!arguments.length) return domain; - domain = x.map(identity); - return identity; - }; - identity.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - identity.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - identity.copy = function() { - return d3_scale_identity(domain); - }; - return identity; - } - d3.svg = {}; - function d3_zero() { - return 0; - } - d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; - function arc() { - var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; - if (r1 < r0) rc = r1, r1 = r0, r0 = rc; - if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; - var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; - if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { - rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); - if (!cw) p1 *= -1; - if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); - if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); - } - if (r1) { - x0 = r1 * Math.cos(a0 + p1); - y0 = r1 * Math.sin(a0 + p1); - x1 = r1 * Math.cos(a1 - p1); - y1 = r1 * Math.sin(a1 - p1); - var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; - if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { - var h1 = (a0 + a1) / 2; - x0 = r1 * Math.cos(h1); - y0 = r1 * Math.sin(h1); - x1 = y1 = null; - } - } else { - x0 = y0 = 0; - } - if (r0) { - x2 = r0 * Math.cos(a1 - p0); - y2 = r0 * Math.sin(a1 - p0); - x3 = r0 * Math.cos(a0 + p0); - y3 = r0 * Math.sin(a0 + p0); - var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; - if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { - var h0 = (a0 + a1) / 2; - x2 = r0 * Math.cos(h0); - y2 = r0 * Math.sin(h0); - x3 = y3 = null; - } - } else { - x2 = y2 = 0; - } - if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { - cr = r0 < r1 ^ cw ? 0 : 1; - var rc1 = rc, rc0 = rc; - if (da < π) { - var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); - rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); - rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); - } - if (x1 != null) { - var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); - if (rc === rc1) { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); - } else { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); - } - } else { - path.push("M", x0, ",", y0); - } - if (x3 != null) { - var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); - if (rc === rc0) { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } else { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } - } else { - path.push("L", x2, ",", y2); - } - } else { - path.push("M", x0, ",", y0); - if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); - path.push("L", x2, ",", y2); - if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); - } - path.push("Z"); - return path.join(""); - } - function circleSegment(r1, cw) { - return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; - } - arc.innerRadius = function(v) { - if (!arguments.length) return innerRadius; - innerRadius = d3_functor(v); - return arc; - }; - arc.outerRadius = function(v) { - if (!arguments.length) return outerRadius; - outerRadius = d3_functor(v); - return arc; - }; - arc.cornerRadius = function(v) { - if (!arguments.length) return cornerRadius; - cornerRadius = d3_functor(v); - return arc; - }; - arc.padRadius = function(v) { - if (!arguments.length) return padRadius; - padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); - return arc; - }; - arc.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return arc; - }; - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return arc; - }; - arc.padAngle = function(v) { - if (!arguments.length) return padAngle; - padAngle = d3_functor(v); - return arc; - }; - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; - return [ Math.cos(a) * r, Math.sin(a) * r ]; - }; - return arc; - }; - var d3_svg_arcAuto = "auto"; - function d3_svg_arcInnerRadius(d) { - return d.innerRadius; - } - function d3_svg_arcOuterRadius(d) { - return d.outerRadius; - } - function d3_svg_arcStartAngle(d) { - return d.startAngle; - } - function d3_svg_arcEndAngle(d) { - return d.endAngle; - } - function d3_svg_arcPadAngle(d) { - return d && d.padAngle; - } - function d3_svg_arcSweep(x0, y0, x1, y1) { - return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; - } - function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { - var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; - return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; - } - function d3_svg_line(projection) { - var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; - function line(data) { - var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); - function segment() { - segments.push("M", interpolate(projection(points), tension)); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); - } else if (points.length) { - segment(); - points = []; - } - } - if (points.length) segment(); - return segments.length ? segments.join("") : null; - } - line.x = function(_) { - if (!arguments.length) return x; - x = _; - return line; - }; - line.y = function(_) { - if (!arguments.length) return y; - y = _; - return line; - }; - line.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return line; - }; - line.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - return line; - }; - line.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return line; - }; - return line; - } - d3.svg.line = function() { - return d3_svg_line(d3_identity); - }; - var d3_svg_lineInterpolators = d3.map({ - linear: d3_svg_lineLinear, - "linear-closed": d3_svg_lineLinearClosed, - step: d3_svg_lineStep, - "step-before": d3_svg_lineStepBefore, - "step-after": d3_svg_lineStepAfter, - basis: d3_svg_lineBasis, - "basis-open": d3_svg_lineBasisOpen, - "basis-closed": d3_svg_lineBasisClosed, - bundle: d3_svg_lineBundle, - cardinal: d3_svg_lineCardinal, - "cardinal-open": d3_svg_lineCardinalOpen, - "cardinal-closed": d3_svg_lineCardinalClosed, - monotone: d3_svg_lineMonotone - }); - d3_svg_lineInterpolators.forEach(function(key, value) { - value.key = key; - value.closed = /-closed$/.test(key); - }); - function d3_svg_lineLinear(points) { - return points.length > 1 ? points.join("L") : points + "Z"; - } - function d3_svg_lineLinearClosed(points) { - return points.join("L") + "Z"; - } - function d3_svg_lineStep(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); - if (n > 1) path.push("H", p[0]); - return path.join(""); - } - function d3_svg_lineStepBefore(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); - return path.join(""); - } - function d3_svg_lineStepAfter(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); - return path.join(""); - } - function d3_svg_lineCardinalOpen(points, tension) { - return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineCardinalClosed(points, tension) { - return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), - points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); - } - function d3_svg_lineCardinal(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineHermite(points, tangents) { - if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { - return d3_svg_lineLinear(points); - } - var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; - if (quad) { - path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; - p0 = points[1]; - pi = 2; - } - if (tangents.length > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - for (var i = 2; i < tangents.length; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - } - } - if (quad) { - var lp = points[pi]; - path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; - } - return path; - } - function d3_svg_lineCardinalTangents(points, tension) { - var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; - while (++i < n) { - p0 = p1; - p1 = p2; - p2 = points[i]; - tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); - } - return tangents; - } - function d3_svg_lineBasis(points) { - if (points.length < 3) return d3_svg_lineLinear(points); - var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - points.push(points[n - 1]); - while (++i <= n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - points.pop(); - path.push("L", pi); - return path.join(""); - } - function d3_svg_lineBasisOpen(points) { - if (points.length < 4) return d3_svg_lineLinear(points); - var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; - while (++i < 3) { - pi = points[i]; - px.push(pi[0]); - py.push(pi[1]); - } - path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); - --i; - while (++i < n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBasisClosed(points) { - var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; - while (++i < 4) { - pi = points[i % n]; - px.push(pi[0]); - py.push(pi[1]); - } - path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - --i; - while (++i < m) { - pi = points[i % n]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBundle(points, tension) { - var n = points.length - 1; - if (n) { - var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; - while (++i <= n) { - p = points[i]; - t = i / n; - p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); - p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); - } - } - return d3_svg_lineBasis(points); - } - function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; - } - var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; - function d3_svg_lineBasisBezier(path, x, y) { - path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); - } - function d3_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); - } - function d3_svg_lineFiniteDifferences(points) { - var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); - while (++i < j) { - m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; - } - m[i] = d; - return m; - } - function d3_svg_lineMonotoneTangents(points) { - var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; - while (++i < j) { - d = d3_svg_lineSlope(points[i], points[i + 1]); - if (abs(d) < ε) { - m[i] = m[i + 1] = 0; - } else { - a = m[i] / d; - b = m[i + 1] / d; - s = a * a + b * b; - if (s > 9) { - s = d * 3 / Math.sqrt(s); - m[i] = s * a; - m[i + 1] = s * b; - } - } - } - i = -1; - while (++i <= j) { - s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); - tangents.push([ s || 0, m[i] * s || 0 ]); - } - return tangents; - } - function d3_svg_lineMonotone(points) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); - } - d3.svg.line.radial = function() { - var line = d3_svg_line(d3_svg_lineRadial); - line.radius = line.x, delete line.x; - line.angle = line.y, delete line.y; - return line; - }; - function d3_svg_lineRadial(points) { - var point, i = -1, n = points.length, r, a; - while (++i < n) { - point = points[i]; - r = point[0]; - a = point[1] - halfπ; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; - } - function d3_svg_area(projection) { - var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; - function area(data) { - var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { - return x; - } : d3_functor(x1), fy1 = y0 === y1 ? function() { - return y; - } : d3_functor(y1), x, y; - function segment() { - segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); - points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); - } else if (points0.length) { - segment(); - points0 = []; - points1 = []; - } - } - if (points0.length) segment(); - return segments.length ? segments.join("") : null; - } - area.x = function(_) { - if (!arguments.length) return x1; - x0 = x1 = _; - return area; - }; - area.x0 = function(_) { - if (!arguments.length) return x0; - x0 = _; - return area; - }; - area.x1 = function(_) { - if (!arguments.length) return x1; - x1 = _; - return area; - }; - area.y = function(_) { - if (!arguments.length) return y1; - y0 = y1 = _; - return area; - }; - area.y0 = function(_) { - if (!arguments.length) return y0; - y0 = _; - return area; - }; - area.y1 = function(_) { - if (!arguments.length) return y1; - y1 = _; - return area; - }; - area.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return area; - }; - area.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - interpolateReverse = interpolate.reverse || interpolate; - L = interpolate.closed ? "M" : "L"; - return area; - }; - area.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return area; - }; - return area; - } - d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; - d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; - d3.svg.area = function() { - return d3_svg_area(d3_identity); - }; - d3.svg.area.radial = function() { - var area = d3_svg_area(d3_svg_lineRadial); - area.radius = area.x, delete area.x; - area.innerRadius = area.x0, delete area.x0; - area.outerRadius = area.x1, delete area.x1; - area.angle = area.y, delete area.y; - area.startAngle = area.y0, delete area.y0; - area.endAngle = area.y1, delete area.y1; - return area; - }; - d3.svg.chord = function() { - var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function chord(d, i) { - var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); - return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; - } - function subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; - return { - r: r, - a0: a0, - a1: a1, - p0: [ r * Math.cos(a0), r * Math.sin(a0) ], - p1: [ r * Math.cos(a1), r * Math.sin(a1) ] - }; - } - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; - } - function arc(r, p, a) { - return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; - } - function curve(r0, p0, r1, p1) { - return "Q 0,0 " + p1; - } - chord.radius = function(v) { - if (!arguments.length) return radius; - radius = d3_functor(v); - return chord; - }; - chord.source = function(v) { - if (!arguments.length) return source; - source = d3_functor(v); - return chord; - }; - chord.target = function(v) { - if (!arguments.length) return target; - target = d3_functor(v); - return chord; - }; - chord.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return chord; - }; - chord.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return chord; - }; - return chord; - }; - function d3_svg_chordRadius(d) { - return d.radius; - } - d3.svg.diagonal = function() { - var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; - function diagonal(d, i) { - var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { - x: p0.x, - y: m - }, { - x: p3.x, - y: m - }, p3 ]; - p = p.map(projection); - return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; - } - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3_functor(x); - return diagonal; - }; - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3_functor(x); - return diagonal; - }; - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; - }; - return diagonal; - }; - function d3_svg_diagonalProjection(d) { - return [ d.x, d.y ]; - } - d3.svg.diagonal.radial = function() { - var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; - diagonal.projection = function(x) { - return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; - }; - return diagonal; - }; - function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; - return [ r * Math.cos(a), r * Math.sin(a) ]; - }; - } - d3.svg.symbol = function() { - var type = d3_svg_symbolType, size = d3_svg_symbolSize; - function symbol(d, i) { - return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); - } - symbol.type = function(x) { - if (!arguments.length) return type; - type = d3_functor(x); - return symbol; - }; - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3_functor(x); - return symbol; - }; - return symbol; - }; - function d3_svg_symbolSize() { - return 64; - } - function d3_svg_symbolType() { - return "circle"; - } - function d3_svg_symbolCircle(size) { - var r = Math.sqrt(size / π); - return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; - } - var d3_svg_symbols = d3.map({ - circle: d3_svg_symbolCircle, - cross: function(size) { - var r = Math.sqrt(size / 5) / 2; - return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; - }, - diamond: function(size) { - var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; - return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; - }, - square: function(size) { - var r = Math.sqrt(size) / 2; - return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; - }, - "triangle-down": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; - }, - "triangle-up": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; - } - }); - d3.svg.symbolTypes = d3_svg_symbols.keys(); - var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); - d3_selectionPrototype.transition = function(name) { - var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { - time: Date.now(), - ease: d3_ease_cubicInOut, - delay: 0, - duration: 250 - }; - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id); - }; - d3_selectionPrototype.interrupt = function(name) { - return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); - }; - var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); - function d3_selection_interruptNS(ns) { - return function() { - var lock, activeId, active; - if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { - active.timer.c = null; - active.timer.t = NaN; - if (--lock.count) delete lock[activeId]; else delete this[ns]; - lock.active += .5; - active.event && active.event.interrupt.call(this, this.__data__, active.index); - } - }; - } - function d3_transition(groups, ns, id) { - d3_subclass(groups, d3_transitionPrototype); - groups.namespace = ns; - groups.id = id; - return groups; - } - var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; - d3_transitionPrototype.call = d3_selectionPrototype.call; - d3_transitionPrototype.empty = d3_selectionPrototype.empty; - d3_transitionPrototype.node = d3_selectionPrototype.node; - d3_transitionPrototype.size = d3_selectionPrototype.size; - d3.transition = function(selection, name) { - return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); - }; - d3.transition.prototype = d3_transitionPrototype; - d3_transitionPrototype.select = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - d3_transitionNode(subnode, i, ns, id, node[ns][id]); - subgroup.push(subnode); - } else { - subgroup.push(null); - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.selectAll = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - transition = node[ns][id]; - subnodes = selector.call(node, node.__data__, i, j); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o; ) { - if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); - subgroup.push(subnode); - } - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_transition(subgroups, this.namespace, this.id); - }; - d3_transitionPrototype.tween = function(name, tween) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) return this.node()[ns][id].tween.get(name); - return d3_selection_each(this, tween == null ? function(node) { - node[ns][id].tween.remove(name); - } : function(node) { - node[ns][id].tween.set(name, tween); - }); - }; - function d3_transition_tween(groups, name, value, tween) { - var id = groups.id, ns = groups.namespace; - return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { - node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); - } : (value = tween(value), function(node) { - node[ns][id].tween.set(name, value); - })); - } - d3_transitionPrototype.attr = function(nameNS, value) { - if (arguments.length < 2) { - for (value in nameNS) this.attr(value, nameNS[value]); - return this; - } - var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrTween(b) { - return b == null ? attrNull : (b += "", function() { - var a = this.getAttribute(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttribute(name, i(t)); - }); - }); - } - function attrTweenNS(b) { - return b == null ? attrNullNS : (b += "", function() { - var a = this.getAttributeNS(name.space, name.local), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttributeNS(name.space, name.local, i(t)); - }); - }); - } - return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.attrTween = function(nameNS, tween) { - var name = d3.ns.qualify(nameNS); - function attrTween(d, i) { - var f = tween.call(this, d, i, this.getAttribute(name)); - return f && function(t) { - this.setAttribute(name, f(t)); - }; - } - function attrTweenNS(d, i) { - var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); - return f && function(t) { - this.setAttributeNS(name.space, name.local, f(t)); - }; - } - return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.style(priority, name[priority], value); - return this; - } - priority = ""; - } - function styleNull() { - this.style.removeProperty(name); - } - function styleString(b) { - return b == null ? styleNull : (b += "", function() { - var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; - return a !== b && (i = d3_interpolate(a, b), function(t) { - this.style.setProperty(name, i(t), priority); - }); - }); - } - return d3_transition_tween(this, "style." + name, value, styleString); - }; - d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - function styleTween(d, i) { - var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); - return f && function(t) { - this.style.setProperty(name, f(t), priority); - }; - } - return this.tween("style." + name, styleTween); - }; - d3_transitionPrototype.text = function(value) { - return d3_transition_tween(this, "text", value, d3_transition_text); - }; - function d3_transition_text(b) { - if (b == null) b = ""; - return function() { - this.textContent = b; - }; - } - d3_transitionPrototype.remove = function() { - var ns = this.namespace; - return this.each("end.transition", function() { - var p; - if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); - }); - }; - d3_transitionPrototype.ease = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].ease; - if (typeof value !== "function") value = d3.ease.apply(d3, arguments); - return d3_selection_each(this, function(node) { - node[ns][id].ease = value; - }); - }; - d3_transitionPrototype.delay = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].delay; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].delay = +value.call(node, node.__data__, i, j); - } : (value = +value, function(node) { - node[ns][id].delay = value; - })); - }; - d3_transitionPrototype.duration = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].duration; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); - } : (value = Math.max(1, value), function(node) { - node[ns][id].duration = value; - })); - }; - d3_transitionPrototype.each = function(type, listener) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) { - var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; - try { - d3_transitionInheritId = id; - d3_selection_each(this, function(node, i, j) { - d3_transitionInherit = node[ns][id]; - type.call(node, node.__data__, i, j); - }); - } finally { - d3_transitionInherit = inherit; - d3_transitionInheritId = inheritId; - } - } else { - d3_selection_each(this, function(node) { - var transition = node[ns][id]; - (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); - }); - } - return this; - }; - d3_transitionPrototype.transition = function() { - var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if (node = group[i]) { - transition = node[ns][id0]; - d3_transitionNode(node, i, ns, id1, { - time: transition.time, - ease: transition.ease, - delay: transition.delay + transition.duration, - duration: transition.duration - }); - } - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id1); - }; - function d3_transitionNamespace(name) { - return name == null ? "__transition__" : "__transition_" + name + "__"; - } - function d3_transitionNode(node, i, ns, id, inherit) { - var lock = node[ns] || (node[ns] = { - active: 0, - count: 0 - }), transition = lock[id], time, timer, duration, ease, tweens; - function schedule(elapsed) { - var delay = transition.delay; - timer.t = delay + time; - if (delay <= elapsed) return start(elapsed - delay); - timer.c = start; - } - function start(elapsed) { - var activeId = lock.active, active = lock[activeId]; - if (active) { - active.timer.c = null; - active.timer.t = NaN; - --lock.count; - delete lock[activeId]; - active.event && active.event.interrupt.call(node, node.__data__, active.index); - } - for (var cancelId in lock) { - if (+cancelId < id) { - var cancel = lock[cancelId]; - cancel.timer.c = null; - cancel.timer.t = NaN; - --lock.count; - delete lock[cancelId]; - } - } - timer.c = tick; - d3_timer(function() { - if (timer.c && tick(elapsed || 1)) { - timer.c = null; - timer.t = NaN; - } - return 1; - }, 0, time); - lock.active = id; - transition.event && transition.event.start.call(node, node.__data__, i); - tweens = []; - transition.tween.forEach(function(key, value) { - if (value = value.call(node, node.__data__, i)) { - tweens.push(value); - } - }); - ease = transition.ease; - duration = transition.duration; - } - function tick(elapsed) { - var t = elapsed / duration, e = ease(t), n = tweens.length; - while (n > 0) { - tweens[--n].call(node, e); - } - if (t >= 1) { - transition.event && transition.event.end.call(node, node.__data__, i); - if (--lock.count) delete lock[id]; else delete node[ns]; - return 1; - } - } - if (!transition) { - time = inherit.time; - timer = d3_timer(schedule, 0, time); - transition = lock[id] = { - tween: new d3_Map(), - time: time, - timer: timer, - delay: inherit.delay, - duration: inherit.duration, - ease: inherit.ease, - index: i - }; - inherit = null; - ++lock.count; - } - } - d3.svg.axis = function() { - var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; - function axis(g) { - g.each(function() { - var g = d3.select(this); - var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); - var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; - var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), - d3.transition(path)); - tickEnter.append("line"); - tickEnter.append("text"); - var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; - if (orient === "bottom" || orient === "top") { - tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; - text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); - } else { - tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; - text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); - pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); - } - lineEnter.attr(y2, sign * innerTickSize); - textEnter.attr(y1, sign * tickSpacing); - lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); - textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); - if (scale1.rangeBand) { - var x = scale1, dx = x.rangeBand() / 2; - scale0 = scale1 = function(d) { - return x(d) + dx; - }; - } else if (scale0.rangeBand) { - scale0 = scale1; - } else { - tickExit.call(tickTransform, scale1, scale0); - } - tickEnter.call(tickTransform, scale0, scale1); - tickUpdate.call(tickTransform, scale1, scale1); - }); - } - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; - }; - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; - return axis; - }; - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = d3_array(arguments); - return axis; - }; - axis.tickValues = function(x) { - if (!arguments.length) return tickValues; - tickValues = x; - return axis; - }; - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; - }; - axis.tickSize = function(x) { - var n = arguments.length; - if (!n) return innerTickSize; - innerTickSize = +x; - outerTickSize = +arguments[n - 1]; - return axis; - }; - axis.innerTickSize = function(x) { - if (!arguments.length) return innerTickSize; - innerTickSize = +x; - return axis; - }; - axis.outerTickSize = function(x) { - if (!arguments.length) return outerTickSize; - outerTickSize = +x; - return axis; - }; - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; - }; - axis.tickSubdivide = function() { - return arguments.length && axis; - }; - return axis; - }; - var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { - top: 1, - right: 1, - bottom: 1, - left: 1 - }; - function d3_svg_axisX(selection, x0, x1) { - selection.attr("transform", function(d) { - var v0 = x0(d); - return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; - }); - } - function d3_svg_axisY(selection, y0, y1) { - selection.attr("transform", function(d) { - var v0 = y0(d); - return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; - }); - } - d3.svg.brush = function() { - var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; - function brush(g) { - g.each(function() { - var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); - var background = g.selectAll(".background").data([ 0 ]); - background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); - g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); - var resize = g.selectAll(".resize").data(resizes, d3_identity); - resize.exit().remove(); - resize.enter().append("g").attr("class", function(d) { - return "resize " + d; - }).style("cursor", function(d) { - return d3_svg_brushCursor[d]; - }).append("rect").attr("x", function(d) { - return /[ew]$/.test(d) ? -3 : null; - }).attr("y", function(d) { - return /^[ns]/.test(d) ? -3 : null; - }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); - resize.style("display", brush.empty() ? "none" : null); - var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; - if (x) { - range = d3_scaleRange(x); - backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); - redrawX(gUpdate); - } - if (y) { - range = d3_scaleRange(y); - backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); - redrawY(gUpdate); - } - redraw(gUpdate); - }); - } - brush.event = function(g) { - g.each(function() { - var event_ = event.of(this, arguments), extent1 = { - x: xExtent, - y: yExtent, - i: xExtentDomain, - j: yExtentDomain - }, extent0 = this.__chart__ || extent1; - this.__chart__ = extent1; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.brush", function() { - xExtentDomain = extent0.i; - yExtentDomain = extent0.j; - xExtent = extent0.x; - yExtent = extent0.y; - event_({ - type: "brushstart" - }); - }).tween("brush:brush", function() { - var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); - xExtentDomain = yExtentDomain = null; - return function(t) { - xExtent = extent1.x = xi(t); - yExtent = extent1.y = yi(t); - event_({ - type: "brush", - mode: "resize" - }); - }; - }).each("end.brush", function() { - xExtentDomain = extent1.i; - yExtentDomain = extent1.j; - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - }); - } else { - event_({ - type: "brushstart" - }); - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - } - }); - }; - function redraw(g) { - g.selectAll(".resize").attr("transform", function(d) { - return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; - }); - } - function redrawX(g) { - g.select(".extent").attr("x", xExtent[0]); - g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); - } - function redrawY(g) { - g.select(".extent").attr("y", yExtent[0]); - g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); - } - function brushstart() { - var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; - var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); - if (d3.event.changedTouches) { - w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); - } else { - w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); - } - g.interrupt().selectAll("*").interrupt(); - if (dragging) { - origin[0] = xExtent[0] - origin[0]; - origin[1] = yExtent[0] - origin[1]; - } else if (resizing) { - var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); - offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; - origin[0] = xExtent[ex]; - origin[1] = yExtent[ey]; - } else if (d3.event.altKey) center = origin.slice(); - g.style("pointer-events", "none").selectAll(".resize").style("display", null); - d3.select("body").style("cursor", eventTarget.style("cursor")); - event_({ - type: "brushstart" - }); - brushmove(); - function keydown() { - if (d3.event.keyCode == 32) { - if (!dragging) { - center = null; - origin[0] -= xExtent[1]; - origin[1] -= yExtent[1]; - dragging = 2; - } - d3_eventPreventDefault(); - } - } - function keyup() { - if (d3.event.keyCode == 32 && dragging == 2) { - origin[0] += xExtent[1]; - origin[1] += yExtent[1]; - dragging = 0; - d3_eventPreventDefault(); - } - } - function brushmove() { - var point = d3.mouse(target), moved = false; - if (offset) { - point[0] += offset[0]; - point[1] += offset[1]; - } - if (!dragging) { - if (d3.event.altKey) { - if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; - origin[0] = xExtent[+(point[0] < center[0])]; - origin[1] = yExtent[+(point[1] < center[1])]; - } else center = null; - } - if (resizingX && move1(point, x, 0)) { - redrawX(g); - moved = true; - } - if (resizingY && move1(point, y, 1)) { - redrawY(g); - moved = true; - } - if (moved) { - redraw(g); - event_({ - type: "brush", - mode: dragging ? "move" : "resize" - }); - } - } - function move1(point, scale, i) { - var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; - if (dragging) { - r0 -= position; - r1 -= size + position; - } - min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; - if (dragging) { - max = (min += position) + size; - } else { - if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); - if (position < min) { - max = min; - min = position; - } else { - max = position; - } - } - if (extent[0] != min || extent[1] != max) { - if (i) yExtentDomain = null; else xExtentDomain = null; - extent[0] = min; - extent[1] = max; - return true; - } - } - function brushend() { - brushmove(); - g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); - d3.select("body").style("cursor", null); - w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); - dragRestore(); - event_({ - type: "brushend" - }); - } - } - brush.x = function(z) { - if (!arguments.length) return x; - x = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.y = function(z) { - if (!arguments.length) return y; - y = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.clamp = function(z) { - if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; - if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; - return brush; - }; - brush.extent = function(z) { - var x0, x1, y0, y1, t; - if (!arguments.length) { - if (x) { - if (xExtentDomain) { - x0 = xExtentDomain[0], x1 = xExtentDomain[1]; - } else { - x0 = xExtent[0], x1 = xExtent[1]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - } - if (y) { - if (yExtentDomain) { - y0 = yExtentDomain[0], y1 = yExtentDomain[1]; - } else { - y0 = yExtent[0], y1 = yExtent[1]; - if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - } - } - return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; - } - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - xExtentDomain = [ x0, x1 ]; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - yExtentDomain = [ y0, y1 ]; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; - } - return brush; - }; - brush.clear = function() { - if (!brush.empty()) { - xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; - xExtentDomain = yExtentDomain = null; - } - return brush; - }; - brush.empty = function() { - return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; - }; - return d3.rebind(brush, event, "on"); - }; - var d3_svg_brushCursor = { - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" - }; - var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; - var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; - var d3_time_formatUtc = d3_time_format.utc; - var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); - d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; - function d3_time_formatIsoNative(date) { - return date.toISOString(); - } - d3_time_formatIsoNative.parse = function(string) { - var date = new Date(string); - return isNaN(date) ? null : date; - }; - d3_time_formatIsoNative.toString = d3_time_formatIso.toString; - d3_time.second = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 1e3) * 1e3); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 1e3); - }, function(date) { - return date.getSeconds(); - }); - d3_time.seconds = d3_time.second.range; - d3_time.seconds.utc = d3_time.second.utc.range; - d3_time.minute = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 6e4) * 6e4); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 6e4); - }, function(date) { - return date.getMinutes(); - }); - d3_time.minutes = d3_time.minute.range; - d3_time.minutes.utc = d3_time.minute.utc.range; - d3_time.hour = d3_time_interval(function(date) { - var timezone = date.getTimezoneOffset() / 60; - return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 36e5); - }, function(date) { - return date.getHours(); - }); - d3_time.hours = d3_time.hour.range; - d3_time.hours.utc = d3_time.hour.utc.range; - d3_time.month = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setDate(1); - return date; - }, function(date, offset) { - date.setMonth(date.getMonth() + offset); - }, function(date) { - return date.getMonth(); - }); - d3_time.months = d3_time.month.range; - d3_time.months.utc = d3_time.month.utc.range; - function d3_time_scale(linear, methods, format) { - function scale(x) { - return linear(x); - } - scale.invert = function(x) { - return d3_time_scaleDate(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(d3_time_scaleDate); - linear.domain(x); - return scale; - }; - function tickMethod(extent, count) { - var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); - return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { - return d / 31536e6; - }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; - } - scale.nice = function(interval, skip) { - var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); - if (method) interval = method[0], skip = method[1]; - function skipped(date) { - return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; - } - return scale.domain(d3_scale_nice(domain, skip > 1 ? { - floor: function(date) { - while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); - return date; - }, - ceil: function(date) { - while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); - return date; - } - } : interval)); - }; - scale.ticks = function(interval, skip) { - var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { - range: interval - }, skip ]; - if (method) interval = method[0], skip = method[1]; - return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); - }; - scale.tickFormat = function() { - return format; - }; - scale.copy = function() { - return d3_time_scale(linear.copy(), methods, format); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_time_scaleDate(t) { - return new Date(t); - } - var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; - var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; - var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { - return d.getMilliseconds(); - } ], [ ":%S", function(d) { - return d.getSeconds(); - } ], [ "%I:%M", function(d) { - return d.getMinutes(); - } ], [ "%I %p", function(d) { - return d.getHours(); - } ], [ "%a %d", function(d) { - return d.getDay() && d.getDate() != 1; - } ], [ "%b %d", function(d) { - return d.getDate() != 1; - } ], [ "%B", function(d) { - return d.getMonth(); - } ], [ "%Y", d3_true ] ]); - var d3_time_scaleMilliseconds = { - range: function(start, stop, step) { - return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); - }, - floor: d3_identity, - ceil: d3_identity - }; - d3_time_scaleLocalMethods.year = d3_time.year; - d3_time.scale = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); - }; - var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { - return [ m[0].utc, m[1] ]; - }); - var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { - return d.getUTCMilliseconds(); - } ], [ ":%S", function(d) { - return d.getUTCSeconds(); - } ], [ "%I:%M", function(d) { - return d.getUTCMinutes(); - } ], [ "%I %p", function(d) { - return d.getUTCHours(); - } ], [ "%a %d", function(d) { - return d.getUTCDay() && d.getUTCDate() != 1; - } ], [ "%b %d", function(d) { - return d.getUTCDate() != 1; - } ], [ "%B", function(d) { - return d.getUTCMonth(); - } ], [ "%Y", d3_true ] ]); - d3_time_scaleUtcMethods.year = d3_time.year.utc; - d3_time.scale.utc = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); - }; - d3.text = d3_xhrType(function(request) { - return request.responseText; - }); - d3.json = function(url, callback) { - return d3_xhr(url, "application/json", d3_json, callback); - }; - function d3_json(request) { - return JSON.parse(request.responseText); - } - d3.html = function(url, callback) { - return d3_xhr(url, "text/html", d3_html, callback); - }; - function d3_html(request) { - var range = d3_document.createRange(); - range.selectNode(d3_document.body); - return range.createContextualFragment(request.responseText); - } - d3.xml = d3_xhrType(function(request) { - return request.responseXML; - }); - if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; -}(); \ No newline at end of file diff --git a/hal-core/resources/web/js/lib/force-graph.LICENSE.txt b/hal-core/resources/web/js/lib/force-graph.LICENSE.txt deleted file mode 100644 index a36ddd4f..00000000 --- a/hal-core/resources/web/js/lib/force-graph.LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Vasco Asturiano - -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. diff --git a/hal-core/resources/web/js/lib/force-graph.js b/hal-core/resources/web/js/lib/force-graph.js deleted file mode 100644 index 13d6e200..00000000 --- a/hal-core/resources/web/js/lib/force-graph.js +++ /dev/null @@ -1,12201 +0,0 @@ -// Version 1.43.4 force-graph - https://github.com/vasturiano/force-graph -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ForceGraph = factory()); -})(this, (function () { 'use strict'; - - function styleInject(css, ref) { - if ( ref === void 0 ) ref = {}; - var insertAt = ref.insertAt; - - if (!css || typeof document === 'undefined') { return; } - - var head = document.head || document.getElementsByTagName('head')[0]; - var style = document.createElement('style'); - style.type = 'text/css'; - - if (insertAt === 'top') { - if (head.firstChild) { - head.insertBefore(style, head.firstChild); - } else { - head.appendChild(style); - } - } else { - head.appendChild(style); - } - - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); - } - } - - var css_248z = ".force-graph-container canvas {\n display: block;\n user-select: none;\n outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n.force-graph-container .graph-tooltip {\n position: absolute;\n top: 0;\n font-family: sans-serif;\n font-size: 16px;\n padding: 4px;\n border-radius: 3px;\n color: #eee;\n background: rgba(0,0,0,0.65);\n visibility: hidden; /* by default */\n}\n\n.force-graph-container .clickable {\n cursor: pointer;\n}\n\n.force-graph-container .grabbable {\n cursor: move;\n cursor: grab;\n cursor: -moz-grab;\n cursor: -webkit-grab;\n}\n\n.force-graph-container .grabbable:active {\n cursor: grabbing;\n cursor: -moz-grabbing;\n cursor: -webkit-grabbing;\n}\n"; - styleInject(css_248z); - - function _iterableToArrayLimit$2(arr, i) { - var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; - if (null != _i) { - var _s, - _e, - _x, - _r, - _arr = [], - _n = !0, - _d = !1; - try { - if (_x = (_i = _i.call(arr)).next, 0 === i) { - if (Object(_i) !== _i) return; - _n = !1; - } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); - } catch (err) { - _d = !0, _e = err; - } finally { - try { - if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; - } finally { - if (_d) throw _e; - } - } - return _arr; - } - } - function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - enumerableOnly && (symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - })), keys.push.apply(keys, symbols); - } - return keys; - } - function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = null != arguments[i] ? arguments[i] : {}; - i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { - _defineProperty(target, key, source[key]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - return target; - } - function _typeof$1(obj) { - "@babel/helpers - typeof"; - - return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }, _typeof$1(obj); - } - function _defineProperty(obj, key, value) { - key = _toPropertyKey$3(key); - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - return obj; - } - function _setPrototypeOf(o, p) { - _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { - o.__proto__ = p; - return o; - }; - return _setPrototypeOf(o, p); - } - function _isNativeReflectConstruct() { - if (typeof Reflect === "undefined" || !Reflect.construct) return false; - if (Reflect.construct.sham) return false; - if (typeof Proxy === "function") return true; - try { - Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); - return true; - } catch (e) { - return false; - } - } - function _construct(Parent, args, Class) { - if (_isNativeReflectConstruct()) { - _construct = Reflect.construct.bind(); - } else { - _construct = function _construct(Parent, args, Class) { - var a = [null]; - a.push.apply(a, args); - var Constructor = Function.bind.apply(Parent, a); - var instance = new Constructor(); - if (Class) _setPrototypeOf(instance, Class.prototype); - return instance; - }; - } - return _construct.apply(null, arguments); - } - function _slicedToArray$2(arr, i) { - return _arrayWithHoles$2(arr) || _iterableToArrayLimit$2(arr, i) || _unsupportedIterableToArray$3(arr, i) || _nonIterableRest$2(); - } - function _toConsumableArray$2(arr) { - return _arrayWithoutHoles$2(arr) || _iterableToArray$2(arr) || _unsupportedIterableToArray$3(arr) || _nonIterableSpread$2(); - } - function _arrayWithoutHoles$2(arr) { - if (Array.isArray(arr)) return _arrayLikeToArray$3(arr); - } - function _arrayWithHoles$2(arr) { - if (Array.isArray(arr)) return arr; - } - function _iterableToArray$2(iter) { - if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); - } - function _unsupportedIterableToArray$3(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray$3(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$3(o, minLen); - } - function _arrayLikeToArray$3(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; - } - function _nonIterableSpread$2() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _nonIterableRest$2() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _toPrimitive$3(input, hint) { - if (typeof input !== "object" || input === null) return input; - var prim = input[Symbol.toPrimitive]; - if (prim !== undefined) { - var res = prim.call(input, hint || "default"); - if (typeof res !== "object") return res; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return (hint === "string" ? String : Number)(input); - } - function _toPropertyKey$3(arg) { - var key = _toPrimitive$3(arg, "string"); - return typeof key === "symbol" ? key : String(key); - } - - var xhtml = "http://www.w3.org/1999/xhtml"; - - var namespaces = { - svg: "http://www.w3.org/2000/svg", - xhtml: xhtml, - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - - function namespace(name) { - var prefix = name += "", i = prefix.indexOf(":"); - if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); - return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; // eslint-disable-line no-prototype-builtins - } - - function creatorInherit(name) { - return function() { - var document = this.ownerDocument, - uri = this.namespaceURI; - return uri === xhtml && document.documentElement.namespaceURI === xhtml - ? document.createElement(name) - : document.createElementNS(uri, name); - }; - } - - function creatorFixed(fullname) { - return function() { - return this.ownerDocument.createElementNS(fullname.space, fullname.local); - }; - } - - function creator(name) { - var fullname = namespace(name); - return (fullname.local - ? creatorFixed - : creatorInherit)(fullname); - } - - function none() {} - - function selector(selector) { - return selector == null ? none : function() { - return this.querySelector(selector); - }; - } - - function selection_select(select) { - if (typeof select !== "function") select = selector(select); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; - } - } - } - - return new Selection$1(subgroups, this._parents); - } - - // Given something array like (or null), returns something that is strictly an - // array. This is used to ensure that array-like objects passed to d3.selectAll - // or selection.selectAll are converted into proper arrays when creating a - // selection; we don’t ever want to create a selection backed by a live - // HTMLCollection or NodeList. However, note that selection.selectAll will use a - // static NodeList as a group, since it safely derived from querySelectorAll. - function array(x) { - return x == null ? [] : Array.isArray(x) ? x : Array.from(x); - } - - function empty() { - return []; - } - - function selectorAll(selector) { - return selector == null ? empty : function() { - return this.querySelectorAll(selector); - }; - } - - function arrayAll(select) { - return function() { - return array(select.apply(this, arguments)); - }; - } - - function selection_selectAll(select) { - if (typeof select === "function") select = arrayAll(select); - else select = selectorAll(select); - - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - subgroups.push(select.call(node, node.__data__, i, group)); - parents.push(node); - } - } - } - - return new Selection$1(subgroups, parents); - } - - function matcher(selector) { - return function() { - return this.matches(selector); - }; - } - - function childMatcher(selector) { - return function(node) { - return node.matches(selector); - }; - } - - var find$1 = Array.prototype.find; - - function childFind(match) { - return function() { - return find$1.call(this.children, match); - }; - } - - function childFirst() { - return this.firstElementChild; - } - - function selection_selectChild(match) { - return this.select(match == null ? childFirst - : childFind(typeof match === "function" ? match : childMatcher(match))); - } - - var filter = Array.prototype.filter; - - function children() { - return Array.from(this.children); - } - - function childrenFilter(match) { - return function() { - return filter.call(this.children, match); - }; - } - - function selection_selectChildren(match) { - return this.selectAll(match == null ? children - : childrenFilter(typeof match === "function" ? match : childMatcher(match))); - } - - function selection_filter(match) { - if (typeof match !== "function") match = matcher(match); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } - - return new Selection$1(subgroups, this._parents); - } - - function sparse(update) { - return new Array(update.length); - } - - function selection_enter() { - return new Selection$1(this._enter || this._groups.map(sparse), this._parents); - } - - function EnterNode(parent, datum) { - this.ownerDocument = parent.ownerDocument; - this.namespaceURI = parent.namespaceURI; - this._next = null; - this._parent = parent; - this.__data__ = datum; - } - - EnterNode.prototype = { - constructor: EnterNode, - appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, - insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, - querySelector: function(selector) { return this._parent.querySelector(selector); }, - querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } - }; - - function constant$4(x) { - return function() { - return x; - }; - } - - function bindIndex(parent, group, enter, update, exit, data) { - var i = 0, - node, - groupLength = group.length, - dataLength = data.length; - - // Put any non-null nodes that fit into update. - // Put any null nodes into enter. - // Put any remaining data into enter. - for (; i < dataLength; ++i) { - if (node = group[i]) { - node.__data__ = data[i]; - update[i] = node; - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } - - // Put any non-null nodes that don’t fit into exit. - for (; i < groupLength; ++i) { - if (node = group[i]) { - exit[i] = node; - } - } - } - - function bindKey(parent, group, enter, update, exit, data, key) { - var i, - node, - nodeByKeyValue = new Map, - groupLength = group.length, - dataLength = data.length, - keyValues = new Array(groupLength), - keyValue; - - // Compute the key for each node. - // If multiple nodes have the same key, the duplicates are added to exit. - for (i = 0; i < groupLength; ++i) { - if (node = group[i]) { - keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + ""; - if (nodeByKeyValue.has(keyValue)) { - exit[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - } - } - - // Compute the key for each datum. - // If there a node associated with this key, join and add it to update. - // If there is not (or the key is a duplicate), add it to enter. - for (i = 0; i < dataLength; ++i) { - keyValue = key.call(parent, data[i], i, data) + ""; - if (node = nodeByKeyValue.get(keyValue)) { - update[i] = node; - node.__data__ = data[i]; - nodeByKeyValue.delete(keyValue); - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } - - // Add any remaining nodes that were not bound to data to exit. - for (i = 0; i < groupLength; ++i) { - if ((node = group[i]) && (nodeByKeyValue.get(keyValues[i]) === node)) { - exit[i] = node; - } - } - } - - function datum(node) { - return node.__data__; - } - - function selection_data(value, key) { - if (!arguments.length) return Array.from(this, datum); - - var bind = key ? bindKey : bindIndex, - parents = this._parents, - groups = this._groups; - - if (typeof value !== "function") value = constant$4(value); - - for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { - var parent = parents[j], - group = groups[j], - groupLength = group.length, - data = arraylike(value.call(parent, parent && parent.__data__, j, parents)), - dataLength = data.length, - enterGroup = enter[j] = new Array(dataLength), - updateGroup = update[j] = new Array(dataLength), - exitGroup = exit[j] = new Array(groupLength); - - bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); - - // Now connect the enter nodes to their following update node, such that - // appendChild can insert the materialized enter node before this node, - // rather than at the end of the parent node. - for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { - if (previous = enterGroup[i0]) { - if (i0 >= i1) i1 = i0 + 1; - while (!(next = updateGroup[i1]) && ++i1 < dataLength); - previous._next = next || null; - } - } - } - - update = new Selection$1(update, parents); - update._enter = enter; - update._exit = exit; - return update; - } - - // Given some data, this returns an array-like view of it: an object that - // exposes a length property and allows numeric indexing. Note that unlike - // selectAll, this isn’t worried about “live” collections because the resulting - // array will only be used briefly while data is being bound. (It is possible to - // cause the data to change while iterating by using a key function, but please - // don’t; we’d rather avoid a gratuitous copy.) - function arraylike(data) { - return typeof data === "object" && "length" in data - ? data // Array, TypedArray, NodeList, array-like - : Array.from(data); // Map, Set, iterable, string, or anything else - } - - function selection_exit() { - return new Selection$1(this._exit || this._groups.map(sparse), this._parents); - } - - function selection_join(onenter, onupdate, onexit) { - var enter = this.enter(), update = this, exit = this.exit(); - if (typeof onenter === "function") { - enter = onenter(enter); - if (enter) enter = enter.selection(); - } else { - enter = enter.append(onenter + ""); - } - if (onupdate != null) { - update = onupdate(update); - if (update) update = update.selection(); - } - if (onexit == null) exit.remove(); else onexit(exit); - return enter && update ? enter.merge(update).order() : update; - } - - function selection_merge(context) { - var selection = context.selection ? context.selection() : context; - - for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } - } - - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } - - return new Selection$1(merges, this._parents); - } - - function selection_order() { - - for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { - for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { - if (node = group[i]) { - if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - - return this; - } - - function selection_sort(compare) { - if (!compare) compare = ascending; - - function compareNode(a, b) { - return a && b ? compare(a.__data__, b.__data__) : !a - !b; - } - - for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group[i]) { - sortgroup[i] = node; - } - } - sortgroup.sort(compareNode); - } - - return new Selection$1(sortgroups, this._parents).order(); - } - - function ascending(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; - } - - function selection_call() { - var callback = arguments[0]; - arguments[0] = this; - callback.apply(null, arguments); - return this; - } - - function selection_nodes() { - return Array.from(this); - } - - function selection_node() { - - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { - var node = group[i]; - if (node) return node; - } - } - - return null; - } - - function selection_size() { - let size = 0; - for (const node of this) ++size; // eslint-disable-line no-unused-vars - return size; - } - - function selection_empty() { - return !this.node(); - } - - function selection_each(callback) { - - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { - if (node = group[i]) callback.call(node, node.__data__, i, group); - } - } - - return this; - } - - function attrRemove$1(name) { - return function() { - this.removeAttribute(name); - }; - } - - function attrRemoveNS$1(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); - }; - } - - function attrConstant$1(name, value) { - return function() { - this.setAttribute(name, value); - }; - } - - function attrConstantNS$1(fullname, value) { - return function() { - this.setAttributeNS(fullname.space, fullname.local, value); - }; - } - - function attrFunction$1(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttribute(name); - else this.setAttribute(name, v); - }; - } - - function attrFunctionNS$1(fullname, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttributeNS(fullname.space, fullname.local); - else this.setAttributeNS(fullname.space, fullname.local, v); - }; - } - - function selection_attr(name, value) { - var fullname = namespace(name); - - if (arguments.length < 2) { - var node = this.node(); - return fullname.local - ? node.getAttributeNS(fullname.space, fullname.local) - : node.getAttribute(fullname); - } - - return this.each((value == null - ? (fullname.local ? attrRemoveNS$1 : attrRemove$1) : (typeof value === "function" - ? (fullname.local ? attrFunctionNS$1 : attrFunction$1) - : (fullname.local ? attrConstantNS$1 : attrConstant$1)))(fullname, value)); - } - - function defaultView(node) { - return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node - || (node.document && node) // node is a Window - || node.defaultView; // node is a Document - } - - function styleRemove$1(name) { - return function() { - this.style.removeProperty(name); - }; - } - - function styleConstant$1(name, value, priority) { - return function() { - this.style.setProperty(name, value, priority); - }; - } - - function styleFunction$1(name, value, priority) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.style.removeProperty(name); - else this.style.setProperty(name, v, priority); - }; - } - - function selection_style(name, value, priority) { - return arguments.length > 1 - ? this.each((value == null - ? styleRemove$1 : typeof value === "function" - ? styleFunction$1 - : styleConstant$1)(name, value, priority == null ? "" : priority)) - : styleValue(this.node(), name); - } - - function styleValue(node, name) { - return node.style.getPropertyValue(name) - || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); - } - - function propertyRemove(name) { - return function() { - delete this[name]; - }; - } - - function propertyConstant(name, value) { - return function() { - this[name] = value; - }; - } - - function propertyFunction(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) delete this[name]; - else this[name] = v; - }; - } - - function selection_property(name, value) { - return arguments.length > 1 - ? this.each((value == null - ? propertyRemove : typeof value === "function" - ? propertyFunction - : propertyConstant)(name, value)) - : this.node()[name]; - } - - function classArray(string) { - return string.trim().split(/^|\s+/); - } - - function classList(node) { - return node.classList || new ClassList(node); - } - - function ClassList(node) { - this._node = node; - this._names = classArray(node.getAttribute("class") || ""); - } - - ClassList.prototype = { - add: function(name) { - var i = this._names.indexOf(name); - if (i < 0) { - this._names.push(name); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - remove: function(name) { - var i = this._names.indexOf(name); - if (i >= 0) { - this._names.splice(i, 1); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - contains: function(name) { - return this._names.indexOf(name) >= 0; - } - }; - - function classedAdd(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.add(names[i]); - } - - function classedRemove(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.remove(names[i]); - } - - function classedTrue(names) { - return function() { - classedAdd(this, names); - }; - } - - function classedFalse(names) { - return function() { - classedRemove(this, names); - }; - } - - function classedFunction(names, value) { - return function() { - (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); - }; - } - - function selection_classed(name, value) { - var names = classArray(name + ""); - - if (arguments.length < 2) { - var list = classList(this.node()), i = -1, n = names.length; - while (++i < n) if (!list.contains(names[i])) return false; - return true; - } - - return this.each((typeof value === "function" - ? classedFunction : value - ? classedTrue - : classedFalse)(names, value)); - } - - function textRemove() { - this.textContent = ""; - } - - function textConstant$1(value) { - return function() { - this.textContent = value; - }; - } - - function textFunction$1(value) { - return function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - }; - } - - function selection_text(value) { - return arguments.length - ? this.each(value == null - ? textRemove : (typeof value === "function" - ? textFunction$1 - : textConstant$1)(value)) - : this.node().textContent; - } - - function htmlRemove() { - this.innerHTML = ""; - } - - function htmlConstant(value) { - return function() { - this.innerHTML = value; - }; - } - - function htmlFunction(value) { - return function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - }; - } - - function selection_html(value) { - return arguments.length - ? this.each(value == null - ? htmlRemove : (typeof value === "function" - ? htmlFunction - : htmlConstant)(value)) - : this.node().innerHTML; - } - - function raise() { - if (this.nextSibling) this.parentNode.appendChild(this); - } - - function selection_raise() { - return this.each(raise); - } - - function lower() { - if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); - } - - function selection_lower() { - return this.each(lower); - } - - function selection_append(name) { - var create = typeof name === "function" ? name : creator(name); - return this.select(function() { - return this.appendChild(create.apply(this, arguments)); - }); - } - - function constantNull() { - return null; - } - - function selection_insert(name, before) { - var create = typeof name === "function" ? name : creator(name), - select = before == null ? constantNull : typeof before === "function" ? before : selector(before); - return this.select(function() { - return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); - }); - } - - function remove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - } - - function selection_remove() { - return this.each(remove); - } - - function selection_cloneShallow() { - var clone = this.cloneNode(false), parent = this.parentNode; - return parent ? parent.insertBefore(clone, this.nextSibling) : clone; - } - - function selection_cloneDeep() { - var clone = this.cloneNode(true), parent = this.parentNode; - return parent ? parent.insertBefore(clone, this.nextSibling) : clone; - } - - function selection_clone(deep) { - return this.select(deep ? selection_cloneDeep : selection_cloneShallow); - } - - function selection_datum(value) { - return arguments.length - ? this.property("__data__", value) - : this.node().__data__; - } - - function contextListener(listener) { - return function(event) { - listener.call(this, event, this.__data__); - }; - } - - function parseTypenames$1(typenames) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - return {type: t, name: name}; - }); - } - - function onRemove(typename) { - return function() { - var on = this.__on; - if (!on) return; - for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { - if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.options); - } else { - on[++i] = o; - } - } - if (++i) on.length = i; - else delete this.__on; - }; - } - - function onAdd(typename, value, options) { - return function() { - var on = this.__on, o, listener = contextListener(value); - if (on) for (var j = 0, m = on.length; j < m; ++j) { - if ((o = on[j]).type === typename.type && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.options); - this.addEventListener(o.type, o.listener = listener, o.options = options); - o.value = value; - return; - } - } - this.addEventListener(typename.type, listener, options); - o = {type: typename.type, name: typename.name, value: value, listener: listener, options: options}; - if (!on) this.__on = [o]; - else on.push(o); - }; - } - - function selection_on(typename, value, options) { - var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; - - if (arguments.length < 2) { - var on = this.node().__on; - if (on) for (var j = 0, m = on.length, o; j < m; ++j) { - for (i = 0, o = on[j]; i < n; ++i) { - if ((t = typenames[i]).type === o.type && t.name === o.name) { - return o.value; - } - } - } - return; - } - - on = value ? onAdd : onRemove; - for (i = 0; i < n; ++i) this.each(on(typenames[i], value, options)); - return this; - } - - function dispatchEvent(node, type, params) { - var window = defaultView(node), - event = window.CustomEvent; - - if (typeof event === "function") { - event = new event(type, params); - } else { - event = window.document.createEvent("Event"); - if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; - else event.initEvent(type, false, false); - } - - node.dispatchEvent(event); - } - - function dispatchConstant(type, params) { - return function() { - return dispatchEvent(this, type, params); - }; - } - - function dispatchFunction(type, params) { - return function() { - return dispatchEvent(this, type, params.apply(this, arguments)); - }; - } - - function selection_dispatch(type, params) { - return this.each((typeof params === "function" - ? dispatchFunction - : dispatchConstant)(type, params)); - } - - function* selection_iterator() { - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { - if (node = group[i]) yield node; - } - } - } - - var root$2 = [null]; - - function Selection$1(groups, parents) { - this._groups = groups; - this._parents = parents; - } - - function selection() { - return new Selection$1([[document.documentElement]], root$2); - } - - function selection_selection() { - return this; - } - - Selection$1.prototype = selection.prototype = { - constructor: Selection$1, - select: selection_select, - selectAll: selection_selectAll, - selectChild: selection_selectChild, - selectChildren: selection_selectChildren, - filter: selection_filter, - data: selection_data, - enter: selection_enter, - exit: selection_exit, - join: selection_join, - merge: selection_merge, - selection: selection_selection, - order: selection_order, - sort: selection_sort, - call: selection_call, - nodes: selection_nodes, - node: selection_node, - size: selection_size, - empty: selection_empty, - each: selection_each, - attr: selection_attr, - style: selection_style, - property: selection_property, - classed: selection_classed, - text: selection_text, - html: selection_html, - raise: selection_raise, - lower: selection_lower, - append: selection_append, - insert: selection_insert, - remove: selection_remove, - clone: selection_clone, - datum: selection_datum, - on: selection_on, - dispatch: selection_dispatch, - [Symbol.iterator]: selection_iterator - }; - - function d3Select(selector) { - return typeof selector === "string" - ? new Selection$1([[document.querySelector(selector)]], [document.documentElement]) - : new Selection$1([[selector]], root$2); - } - - function sourceEvent(event) { - let sourceEvent; - while (sourceEvent = event.sourceEvent) event = sourceEvent; - return event; - } - - function pointer(event, node) { - event = sourceEvent(event); - if (node === undefined) node = event.currentTarget; - if (node) { - var svg = node.ownerSVGElement || node; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - point.x = event.clientX, point.y = event.clientY; - point = point.matrixTransform(node.getScreenCTM().inverse()); - return [point.x, point.y]; - } - if (node.getBoundingClientRect) { - var rect = node.getBoundingClientRect(); - return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; - } - } - return [event.pageX, event.pageY]; - } - - var noop = {value: () => {}}; - - function dispatch() { - for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { - if (!(t = arguments[i] + "") || (t in _) || /[\s.]/.test(t)) throw new Error("illegal type: " + t); - _[t] = []; - } - return new Dispatch(_); - } - - function Dispatch(_) { - this._ = _; - } - - function parseTypenames(typenames, types) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); - return {type: t, name: name}; - }); - } - - Dispatch.prototype = dispatch.prototype = { - constructor: Dispatch, - on: function(typename, callback) { - var _ = this._, - T = parseTypenames(typename + "", _), - t, - i = -1, - n = T.length; - - // If no callback was specified, return the callback of the given type and name. - if (arguments.length < 2) { - while (++i < n) if ((t = (typename = T[i]).type) && (t = get$1(_[t], typename.name))) return t; - return; - } - - // If a type was specified, set the callback for the given type and name. - // Otherwise, if a null callback was specified, remove callbacks of the given name. - if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); - while (++i < n) { - if (t = (typename = T[i]).type) _[t] = set$1(_[t], typename.name, callback); - else if (callback == null) for (t in _) _[t] = set$1(_[t], typename.name, null); - } - - return this; - }, - copy: function() { - var copy = {}, _ = this._; - for (var t in _) copy[t] = _[t].slice(); - return new Dispatch(copy); - }, - call: function(type, that) { - if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - }, - apply: function(type, that, args) { - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - } - }; - - function get$1(type, name) { - for (var i = 0, n = type.length, c; i < n; ++i) { - if ((c = type[i]).name === name) { - return c.value; - } - } - } - - function set$1(type, name, callback) { - for (var i = 0, n = type.length; i < n; ++i) { - if (type[i].name === name) { - type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); - break; - } - } - if (callback != null) type.push({name: name, value: callback}); - return type; - } - - // These are typically used in conjunction with noevent to ensure that we can - // preventDefault on the event. - const nonpassive = {passive: false}; - const nonpassivecapture = {capture: true, passive: false}; - - function nopropagation$1(event) { - event.stopImmediatePropagation(); - } - - function noevent$1(event) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - - function dragDisable(view) { - var root = view.document.documentElement, - selection = d3Select(view).on("dragstart.drag", noevent$1, nonpassivecapture); - if ("onselectstart" in root) { - selection.on("selectstart.drag", noevent$1, nonpassivecapture); - } else { - root.__noselect = root.style.MozUserSelect; - root.style.MozUserSelect = "none"; - } - } - - function yesdrag(view, noclick) { - var root = view.document.documentElement, - selection = d3Select(view).on("dragstart.drag", null); - if (noclick) { - selection.on("click.drag", noevent$1, nonpassivecapture); - setTimeout(function() { selection.on("click.drag", null); }, 0); - } - if ("onselectstart" in root) { - selection.on("selectstart.drag", null); - } else { - root.style.MozUserSelect = root.__noselect; - delete root.__noselect; - } - } - - var constant$3 = x => () => x; - - function DragEvent(type, { - sourceEvent, - subject, - target, - identifier, - active, - x, y, dx, dy, - dispatch - }) { - Object.defineProperties(this, { - type: {value: type, enumerable: true, configurable: true}, - sourceEvent: {value: sourceEvent, enumerable: true, configurable: true}, - subject: {value: subject, enumerable: true, configurable: true}, - target: {value: target, enumerable: true, configurable: true}, - identifier: {value: identifier, enumerable: true, configurable: true}, - active: {value: active, enumerable: true, configurable: true}, - x: {value: x, enumerable: true, configurable: true}, - y: {value: y, enumerable: true, configurable: true}, - dx: {value: dx, enumerable: true, configurable: true}, - dy: {value: dy, enumerable: true, configurable: true}, - _: {value: dispatch} - }); - } - - DragEvent.prototype.on = function() { - var value = this._.on.apply(this._, arguments); - return value === this._ ? this : value; - }; - - // Ignore right-click, since that should open the context menu. - function defaultFilter$1(event) { - return !event.ctrlKey && !event.button; - } - - function defaultContainer() { - return this.parentNode; - } - - function defaultSubject(event, d) { - return d == null ? {x: event.x, y: event.y} : d; - } - - function defaultTouchable$1() { - return navigator.maxTouchPoints || ("ontouchstart" in this); - } - - function d3Drag() { - var filter = defaultFilter$1, - container = defaultContainer, - subject = defaultSubject, - touchable = defaultTouchable$1, - gestures = {}, - listeners = dispatch("start", "drag", "end"), - active = 0, - mousedownx, - mousedowny, - mousemoving, - touchending, - clickDistance2 = 0; - - function drag(selection) { - selection - .on("mousedown.drag", mousedowned) - .filter(touchable) - .on("touchstart.drag", touchstarted) - .on("touchmove.drag", touchmoved, nonpassive) - .on("touchend.drag touchcancel.drag", touchended) - .style("touch-action", "none") - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); - } - - function mousedowned(event, d) { - if (touchending || !filter.call(this, event, d)) return; - var gesture = beforestart(this, container.call(this, event, d), event, d, "mouse"); - if (!gesture) return; - d3Select(event.view) - .on("mousemove.drag", mousemoved, nonpassivecapture) - .on("mouseup.drag", mouseupped, nonpassivecapture); - dragDisable(event.view); - nopropagation$1(event); - mousemoving = false; - mousedownx = event.clientX; - mousedowny = event.clientY; - gesture("start", event); - } - - function mousemoved(event) { - noevent$1(event); - if (!mousemoving) { - var dx = event.clientX - mousedownx, dy = event.clientY - mousedowny; - mousemoving = dx * dx + dy * dy > clickDistance2; - } - gestures.mouse("drag", event); - } - - function mouseupped(event) { - d3Select(event.view).on("mousemove.drag mouseup.drag", null); - yesdrag(event.view, mousemoving); - noevent$1(event); - gestures.mouse("end", event); - } - - function touchstarted(event, d) { - if (!filter.call(this, event, d)) return; - var touches = event.changedTouches, - c = container.call(this, event, d), - n = touches.length, i, gesture; - - for (i = 0; i < n; ++i) { - if (gesture = beforestart(this, c, event, d, touches[i].identifier, touches[i])) { - nopropagation$1(event); - gesture("start", event, touches[i]); - } - } - } - - function touchmoved(event) { - var touches = event.changedTouches, - n = touches.length, i, gesture; - - for (i = 0; i < n; ++i) { - if (gesture = gestures[touches[i].identifier]) { - noevent$1(event); - gesture("drag", event, touches[i]); - } - } - } - - function touchended(event) { - var touches = event.changedTouches, - n = touches.length, i, gesture; - - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! - for (i = 0; i < n; ++i) { - if (gesture = gestures[touches[i].identifier]) { - nopropagation$1(event); - gesture("end", event, touches[i]); - } - } - } - - function beforestart(that, container, event, d, identifier, touch) { - var dispatch = listeners.copy(), - p = pointer(touch || event, container), dx, dy, - s; - - if ((s = subject.call(that, new DragEvent("beforestart", { - sourceEvent: event, - target: drag, - identifier, - active, - x: p[0], - y: p[1], - dx: 0, - dy: 0, - dispatch - }), d)) == null) return; - - dx = s.x - p[0] || 0; - dy = s.y - p[1] || 0; - - return function gesture(type, event, touch) { - var p0 = p, n; - switch (type) { - case "start": gestures[identifier] = gesture, n = active++; break; - case "end": delete gestures[identifier], --active; // falls through - case "drag": p = pointer(touch || event, container), n = active; break; - } - dispatch.call( - type, - that, - new DragEvent(type, { - sourceEvent: event, - subject: s, - target: drag, - identifier, - active: n, - x: p[0] + dx, - y: p[1] + dy, - dx: p[0] - p0[0], - dy: p[1] - p0[1], - dispatch - }), - d - ); - }; - } - - drag.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$3(!!_), drag) : filter; - }; - - drag.container = function(_) { - return arguments.length ? (container = typeof _ === "function" ? _ : constant$3(_), drag) : container; - }; - - drag.subject = function(_) { - return arguments.length ? (subject = typeof _ === "function" ? _ : constant$3(_), drag) : subject; - }; - - drag.touchable = function(_) { - return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$3(!!_), drag) : touchable; - }; - - drag.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? drag : value; - }; - - drag.clickDistance = function(_) { - return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); - }; - - return drag; - } - - function define(constructor, factory, prototype) { - constructor.prototype = factory.prototype = prototype; - prototype.constructor = constructor; - } - - function extend(parent, definition) { - var prototype = Object.create(parent.prototype); - for (var key in definition) prototype[key] = definition[key]; - return prototype; - } - - function Color() {} - - var darker = 0.7; - var brighter = 1 / darker; - - var reI = "\\s*([+-]?\\d+)\\s*", - reN = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*", - reP = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*", - reHex = /^#([0-9a-f]{3,8})$/, - reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`), - reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`), - reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`), - reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`), - reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`), - reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`); - - var named = { - aliceblue: 0xf0f8ff, - antiquewhite: 0xfaebd7, - aqua: 0x00ffff, - aquamarine: 0x7fffd4, - azure: 0xf0ffff, - beige: 0xf5f5dc, - bisque: 0xffe4c4, - black: 0x000000, - blanchedalmond: 0xffebcd, - blue: 0x0000ff, - blueviolet: 0x8a2be2, - brown: 0xa52a2a, - burlywood: 0xdeb887, - cadetblue: 0x5f9ea0, - chartreuse: 0x7fff00, - chocolate: 0xd2691e, - coral: 0xff7f50, - cornflowerblue: 0x6495ed, - cornsilk: 0xfff8dc, - crimson: 0xdc143c, - cyan: 0x00ffff, - darkblue: 0x00008b, - darkcyan: 0x008b8b, - darkgoldenrod: 0xb8860b, - darkgray: 0xa9a9a9, - darkgreen: 0x006400, - darkgrey: 0xa9a9a9, - darkkhaki: 0xbdb76b, - darkmagenta: 0x8b008b, - darkolivegreen: 0x556b2f, - darkorange: 0xff8c00, - darkorchid: 0x9932cc, - darkred: 0x8b0000, - darksalmon: 0xe9967a, - darkseagreen: 0x8fbc8f, - darkslateblue: 0x483d8b, - darkslategray: 0x2f4f4f, - darkslategrey: 0x2f4f4f, - darkturquoise: 0x00ced1, - darkviolet: 0x9400d3, - deeppink: 0xff1493, - deepskyblue: 0x00bfff, - dimgray: 0x696969, - dimgrey: 0x696969, - dodgerblue: 0x1e90ff, - firebrick: 0xb22222, - floralwhite: 0xfffaf0, - forestgreen: 0x228b22, - fuchsia: 0xff00ff, - gainsboro: 0xdcdcdc, - ghostwhite: 0xf8f8ff, - gold: 0xffd700, - goldenrod: 0xdaa520, - gray: 0x808080, - green: 0x008000, - greenyellow: 0xadff2f, - grey: 0x808080, - honeydew: 0xf0fff0, - hotpink: 0xff69b4, - indianred: 0xcd5c5c, - indigo: 0x4b0082, - ivory: 0xfffff0, - khaki: 0xf0e68c, - lavender: 0xe6e6fa, - lavenderblush: 0xfff0f5, - lawngreen: 0x7cfc00, - lemonchiffon: 0xfffacd, - lightblue: 0xadd8e6, - lightcoral: 0xf08080, - lightcyan: 0xe0ffff, - lightgoldenrodyellow: 0xfafad2, - lightgray: 0xd3d3d3, - lightgreen: 0x90ee90, - lightgrey: 0xd3d3d3, - lightpink: 0xffb6c1, - lightsalmon: 0xffa07a, - lightseagreen: 0x20b2aa, - lightskyblue: 0x87cefa, - lightslategray: 0x778899, - lightslategrey: 0x778899, - lightsteelblue: 0xb0c4de, - lightyellow: 0xffffe0, - lime: 0x00ff00, - limegreen: 0x32cd32, - linen: 0xfaf0e6, - magenta: 0xff00ff, - maroon: 0x800000, - mediumaquamarine: 0x66cdaa, - mediumblue: 0x0000cd, - mediumorchid: 0xba55d3, - mediumpurple: 0x9370db, - mediumseagreen: 0x3cb371, - mediumslateblue: 0x7b68ee, - mediumspringgreen: 0x00fa9a, - mediumturquoise: 0x48d1cc, - mediumvioletred: 0xc71585, - midnightblue: 0x191970, - mintcream: 0xf5fffa, - mistyrose: 0xffe4e1, - moccasin: 0xffe4b5, - navajowhite: 0xffdead, - navy: 0x000080, - oldlace: 0xfdf5e6, - olive: 0x808000, - olivedrab: 0x6b8e23, - orange: 0xffa500, - orangered: 0xff4500, - orchid: 0xda70d6, - palegoldenrod: 0xeee8aa, - palegreen: 0x98fb98, - paleturquoise: 0xafeeee, - palevioletred: 0xdb7093, - papayawhip: 0xffefd5, - peachpuff: 0xffdab9, - peru: 0xcd853f, - pink: 0xffc0cb, - plum: 0xdda0dd, - powderblue: 0xb0e0e6, - purple: 0x800080, - rebeccapurple: 0x663399, - red: 0xff0000, - rosybrown: 0xbc8f8f, - royalblue: 0x4169e1, - saddlebrown: 0x8b4513, - salmon: 0xfa8072, - sandybrown: 0xf4a460, - seagreen: 0x2e8b57, - seashell: 0xfff5ee, - sienna: 0xa0522d, - silver: 0xc0c0c0, - skyblue: 0x87ceeb, - slateblue: 0x6a5acd, - slategray: 0x708090, - slategrey: 0x708090, - snow: 0xfffafa, - springgreen: 0x00ff7f, - steelblue: 0x4682b4, - tan: 0xd2b48c, - teal: 0x008080, - thistle: 0xd8bfd8, - tomato: 0xff6347, - turquoise: 0x40e0d0, - violet: 0xee82ee, - wheat: 0xf5deb3, - white: 0xffffff, - whitesmoke: 0xf5f5f5, - yellow: 0xffff00, - yellowgreen: 0x9acd32 - }; - - define(Color, color, { - copy(channels) { - return Object.assign(new this.constructor, this, channels); - }, - displayable() { - return this.rgb().displayable(); - }, - hex: color_formatHex, // Deprecated! Use color.formatHex. - formatHex: color_formatHex, - formatHex8: color_formatHex8, - formatHsl: color_formatHsl, - formatRgb: color_formatRgb, - toString: color_formatRgb - }); - - function color_formatHex() { - return this.rgb().formatHex(); - } - - function color_formatHex8() { - return this.rgb().formatHex8(); - } - - function color_formatHsl() { - return hslConvert(this).formatHsl(); - } - - function color_formatRgb() { - return this.rgb().formatRgb(); - } - - function color(format) { - var m, l; - format = (format + "").trim().toLowerCase(); - return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000 - : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00 - : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000 - : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000 - : null) // invalid hex - : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) - : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) - : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) - : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) - : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) - : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) - : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins - : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) - : null; - } - - function rgbn(n) { - return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); - } - - function rgba(r, g, b, a) { - if (a <= 0) r = g = b = NaN; - return new Rgb(r, g, b, a); - } - - function rgbConvert(o) { - if (!(o instanceof Color)) o = color(o); - if (!o) return new Rgb; - o = o.rgb(); - return new Rgb(o.r, o.g, o.b, o.opacity); - } - - function rgb(r, g, b, opacity) { - return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); - } - - function Rgb(r, g, b, opacity) { - this.r = +r; - this.g = +g; - this.b = +b; - this.opacity = +opacity; - } - - define(Rgb, rgb, extend(Color, { - brighter(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - darker(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - rgb() { - return this; - }, - clamp() { - return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity)); - }, - displayable() { - return (-0.5 <= this.r && this.r < 255.5) - && (-0.5 <= this.g && this.g < 255.5) - && (-0.5 <= this.b && this.b < 255.5) - && (0 <= this.opacity && this.opacity <= 1); - }, - hex: rgb_formatHex, // Deprecated! Use color.formatHex. - formatHex: rgb_formatHex, - formatHex8: rgb_formatHex8, - formatRgb: rgb_formatRgb, - toString: rgb_formatRgb - })); - - function rgb_formatHex() { - return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`; - } - - function rgb_formatHex8() { - return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`; - } - - function rgb_formatRgb() { - const a = clampa(this.opacity); - return `${a === 1 ? "rgb(" : "rgba("}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a === 1 ? ")" : `, ${a})`}`; - } - - function clampa(opacity) { - return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity)); - } - - function clampi(value) { - return Math.max(0, Math.min(255, Math.round(value) || 0)); - } - - function hex(value) { - value = clampi(value); - return (value < 16 ? "0" : "") + value.toString(16); - } - - function hsla(h, s, l, a) { - if (a <= 0) h = s = l = NaN; - else if (l <= 0 || l >= 1) h = s = NaN; - else if (s <= 0) h = NaN; - return new Hsl(h, s, l, a); - } - - function hslConvert(o) { - if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Color)) o = color(o); - if (!o) return new Hsl; - if (o instanceof Hsl) return o; - o = o.rgb(); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - h = NaN, - s = max - min, - l = (max + min) / 2; - if (s) { - if (r === max) h = (g - b) / s + (g < b) * 6; - else if (g === max) h = (b - r) / s + 2; - else h = (r - g) / s + 4; - s /= l < 0.5 ? max + min : 2 - max - min; - h *= 60; - } else { - s = l > 0 && l < 1 ? 0 : h; - } - return new Hsl(h, s, l, o.opacity); - } - - function hsl(h, s, l, opacity) { - return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); - } - - function Hsl(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; - } - - define(Hsl, hsl, extend(Color, { - brighter(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - darker(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - rgb() { - var h = this.h % 360 + (this.h < 0) * 360, - s = isNaN(h) || isNaN(this.s) ? 0 : this.s, - l = this.l, - m2 = l + (l < 0.5 ? l : 1 - l) * s, - m1 = 2 * l - m2; - return new Rgb( - hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), - hsl2rgb(h, m1, m2), - hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), - this.opacity - ); - }, - clamp() { - return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity)); - }, - displayable() { - return (0 <= this.s && this.s <= 1 || isNaN(this.s)) - && (0 <= this.l && this.l <= 1) - && (0 <= this.opacity && this.opacity <= 1); - }, - formatHsl() { - const a = clampa(this.opacity); - return `${a === 1 ? "hsl(" : "hsla("}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? ")" : `, ${a})`}`; - } - })); - - function clamph(value) { - value = (value || 0) % 360; - return value < 0 ? value + 360 : value; - } - - function clampt(value) { - return Math.max(0, Math.min(1, value || 0)); - } - - /* From FvD 13.37, CSS Color Module Level 3 */ - function hsl2rgb(h, m1, m2) { - return (h < 60 ? m1 + (m2 - m1) * h / 60 - : h < 180 ? m2 - : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 - : m1) * 255; - } - - var constant$2 = x => () => x; - - function linear(a, d) { - return function(t) { - return a + t * d; - }; - } - - function exponential(a, b, y) { - return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { - return Math.pow(a + t * b, y); - }; - } - - function gamma(y) { - return (y = +y) === 1 ? nogamma : function(a, b) { - return b - a ? exponential(a, b, y) : constant$2(isNaN(a) ? b : a); - }; - } - - function nogamma(a, b) { - var d = b - a; - return d ? linear(a, d) : constant$2(isNaN(a) ? b : a); - } - - var interpolateRgb = (function rgbGamma(y) { - var color = gamma(y); - - function rgb$1(start, end) { - var r = color((start = rgb(start)).r, (end = rgb(end)).r), - g = color(start.g, end.g), - b = color(start.b, end.b), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.r = r(t); - start.g = g(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; - } - - rgb$1.gamma = rgbGamma; - - return rgb$1; - })(1); - - function interpolateNumber(a, b) { - return a = +a, b = +b, function(t) { - return a * (1 - t) + b * t; - }; - } - - var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, - reB = new RegExp(reA.source, "g"); - - function zero(b) { - return function() { - return b; - }; - } - - function one(b) { - return function(t) { - return b(t) + ""; - }; - } - - function interpolateString(a, b) { - var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b - am, // current match in a - bm, // current match in b - bs, // string preceding current number in b, if any - i = -1, // index in s - s = [], // string constants and placeholders - q = []; // number interpolators - - // Coerce inputs to strings. - a = a + "", b = b + ""; - - // Interpolate pairs of numbers in a & b. - while ((am = reA.exec(a)) - && (bm = reB.exec(b))) { - if ((bs = bm.index) > bi) { // a string precedes the next number in b - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match - if (s[i]) s[i] += bm; // coalesce with previous string - else s[++i] = bm; - } else { // interpolate non-matching numbers - s[++i] = null; - q.push({i: i, x: interpolateNumber(am, bm)}); - } - bi = reB.lastIndex; - } - - // Add remains of b. - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - - // Special optimization for only a single match. - // Otherwise, interpolate each of the numbers and rejoin the string. - return s.length < 2 ? (q[0] - ? one(q[0].x) - : zero(b)) - : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); - } - - var degrees = 180 / Math.PI; - - var identity$1 = { - translateX: 0, - translateY: 0, - rotate: 0, - skewX: 0, - scaleX: 1, - scaleY: 1 - }; - - function decompose(a, b, c, d, e, f) { - var scaleX, scaleY, skewX; - if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; - if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; - if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; - if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; - return { - translateX: e, - translateY: f, - rotate: Math.atan2(b, a) * degrees, - skewX: Math.atan(skewX) * degrees, - scaleX: scaleX, - scaleY: scaleY - }; - } - - var svgNode; - - /* eslint-disable no-undef */ - function parseCss(value) { - const m = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + ""); - return m.isIdentity ? identity$1 : decompose(m.a, m.b, m.c, m.d, m.e, m.f); - } - - function parseSvg(value) { - if (value == null) return identity$1; - if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); - svgNode.setAttribute("transform", value); - if (!(value = svgNode.transform.baseVal.consolidate())) return identity$1; - value = value.matrix; - return decompose(value.a, value.b, value.c, value.d, value.e, value.f); - } - - function interpolateTransform(parse, pxComma, pxParen, degParen) { - - function pop(s) { - return s.length ? s.pop() + " " : ""; - } - - function translate(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push("translate(", null, pxComma, null, pxParen); - q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); - } else if (xb || yb) { - s.push("translate(" + xb + pxComma + yb + pxParen); - } - } - - function rotate(a, b, s, q) { - if (a !== b) { - if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path - q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)}); - } else if (b) { - s.push(pop(s) + "rotate(" + b + degParen); - } - } - - function skewX(a, b, s, q) { - if (a !== b) { - q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)}); - } else if (b) { - s.push(pop(s) + "skewX(" + b + degParen); - } - } - - function scale(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push(pop(s) + "scale(", null, ",", null, ")"); - q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); - } else if (xb !== 1 || yb !== 1) { - s.push(pop(s) + "scale(" + xb + "," + yb + ")"); - } - } - - return function(a, b) { - var s = [], // string constants and placeholders - q = []; // number interpolators - a = parse(a), b = parse(b); - translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); - rotate(a.rotate, b.rotate, s, q); - skewX(a.skewX, b.skewX, s, q); - scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); - a = b = null; // gc - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - }; - } - - var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); - var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); - - var epsilon2 = 1e-12; - - function cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; - } - - function sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; - } - - function tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); - } - - var interpolateZoom = (function zoomRho(rho, rho2, rho4) { - - // p0 = [ux0, uy0, w0] - // p1 = [ux1, uy1, w1] - function zoom(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], - ux1 = p1[0], uy1 = p1[1], w1 = p1[2], - dx = ux1 - ux0, - dy = uy1 - uy0, - d2 = dx * dx + dy * dy, - i, - S; - - // Special case for u0 ≅ u1. - if (d2 < epsilon2) { - S = Math.log(w1 / w0) / rho; - i = function(t) { - return [ - ux0 + t * dx, - uy0 + t * dy, - w0 * Math.exp(rho * t * S) - ]; - }; - } - - // General case. - else { - var d1 = Math.sqrt(d2), - b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), - b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), - r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), - r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); - S = (r1 - r0) / rho; - i = function(t) { - var s = t * S, - coshr0 = cosh(r0), - u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); - return [ - ux0 + u * dx, - uy0 + u * dy, - w0 * coshr0 / cosh(rho * s + r0) - ]; - }; - } - - i.duration = S * 1000 * rho / Math.SQRT2; - - return i; - } - - zoom.rho = function(_) { - var _1 = Math.max(1e-3, +_), _2 = _1 * _1, _4 = _2 * _2; - return zoomRho(_1, _2, _4); - }; - - return zoom; - })(Math.SQRT2, 2, 4); - - var frame = 0, // is an animation frame pending? - timeout$1 = 0, // is a timeout pending? - interval = 0, // are any timers active? - pokeDelay = 1000, // how frequently we check for clock skew - taskHead, - taskTail, - clockLast = 0, - clockNow = 0, - clockSkew = 0, - clock = typeof performance === "object" && performance.now ? performance : Date, - setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; - - function now$3() { - return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); - } - - function clearNow() { - clockNow = 0; - } - - function Timer() { - this._call = - this._time = - this._next = null; - } - - Timer.prototype = timer.prototype = { - constructor: Timer, - restart: function(callback, delay, time) { - if (typeof callback !== "function") throw new TypeError("callback is not a function"); - time = (time == null ? now$3() : +time) + (delay == null ? 0 : +delay); - if (!this._next && taskTail !== this) { - if (taskTail) taskTail._next = this; - else taskHead = this; - taskTail = this; - } - this._call = callback; - this._time = time; - sleep(); - }, - stop: function() { - if (this._call) { - this._call = null; - this._time = Infinity; - sleep(); - } - } - }; - - function timer(callback, delay, time) { - var t = new Timer; - t.restart(callback, delay, time); - return t; - } - - function timerFlush() { - now$3(); // Get the current time, if not already set. - ++frame; // Pretend we’ve set an alarm, if we haven’t already. - var t = taskHead, e; - while (t) { - if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e); - t = t._next; - } - --frame; - } - - function wake() { - clockNow = (clockLast = clock.now()) + clockSkew; - frame = timeout$1 = 0; - try { - timerFlush(); - } finally { - frame = 0; - nap(); - clockNow = 0; - } - } - - function poke() { - var now = clock.now(), delay = now - clockLast; - if (delay > pokeDelay) clockSkew -= delay, clockLast = now; - } - - function nap() { - var t0, t1 = taskHead, t2, time = Infinity; - while (t1) { - if (t1._call) { - if (time > t1._time) time = t1._time; - t0 = t1, t1 = t1._next; - } else { - t2 = t1._next, t1._next = null; - t1 = t0 ? t0._next = t2 : taskHead = t2; - } - } - taskTail = t0; - sleep(time); - } - - function sleep(time) { - if (frame) return; // Soonest alarm already set, or will be. - if (timeout$1) timeout$1 = clearTimeout(timeout$1); - var delay = time - clockNow; // Strictly less than if we recomputed clockNow. - if (delay > 24) { - if (time < Infinity) timeout$1 = setTimeout(wake, time - clock.now() - clockSkew); - if (interval) interval = clearInterval(interval); - } else { - if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); - frame = 1, setFrame(wake); - } - } - - function timeout(callback, delay, time) { - var t = new Timer; - delay = delay == null ? 0 : +delay; - t.restart(elapsed => { - t.stop(); - callback(elapsed + delay); - }, delay, time); - return t; - } - - var emptyOn = dispatch("start", "end", "cancel", "interrupt"); - var emptyTween = []; - - var CREATED = 0; - var SCHEDULED = 1; - var STARTING = 2; - var STARTED = 3; - var RUNNING = 4; - var ENDING = 5; - var ENDED = 6; - - function schedule(node, name, id, index, group, timing) { - var schedules = node.__transition; - if (!schedules) node.__transition = {}; - else if (id in schedules) return; - create(node, id, { - name: name, - index: index, // For context during callback. - group: group, // For context during callback. - on: emptyOn, - tween: emptyTween, - time: timing.time, - delay: timing.delay, - duration: timing.duration, - ease: timing.ease, - timer: null, - state: CREATED - }); - } - - function init(node, id) { - var schedule = get(node, id); - if (schedule.state > CREATED) throw new Error("too late; already scheduled"); - return schedule; - } - - function set(node, id) { - var schedule = get(node, id); - if (schedule.state > STARTED) throw new Error("too late; already running"); - return schedule; - } - - function get(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found"); - return schedule; - } - - function create(node, id, self) { - var schedules = node.__transition, - tween; - - // Initialize the self timer when the transition is created. - // Note the actual delay is not known until the first callback! - schedules[id] = self; - self.timer = timer(schedule, 0, self.time); - - function schedule(elapsed) { - self.state = SCHEDULED; - self.timer.restart(start, self.delay, self.time); - - // If the elapsed delay is less than our first sleep, start immediately. - if (self.delay <= elapsed) start(elapsed - self.delay); - } - - function start(elapsed) { - var i, j, n, o; - - // If the state is not SCHEDULED, then we previously errored on start. - if (self.state !== SCHEDULED) return stop(); - - for (i in schedules) { - o = schedules[i]; - if (o.name !== self.name) continue; - - // While this element already has a starting transition during this frame, - // defer starting an interrupting transition until that transition has a - // chance to tick (and possibly end); see d3/d3-transition#54! - if (o.state === STARTED) return timeout(start); - - // Interrupt the active transition, if any. - if (o.state === RUNNING) { - o.state = ENDED; - o.timer.stop(); - o.on.call("interrupt", node, node.__data__, o.index, o.group); - delete schedules[i]; - } - - // Cancel any pre-empted transitions. - else if (+i < id) { - o.state = ENDED; - o.timer.stop(); - o.on.call("cancel", node, node.__data__, o.index, o.group); - delete schedules[i]; - } - } - - // Defer the first tick to end of the current frame; see d3/d3#1576. - // Note the transition may be canceled after start and before the first tick! - // Note this must be scheduled before the start event; see d3/d3-transition#16! - // Assuming this is successful, subsequent callbacks go straight to tick. - timeout(function() { - if (self.state === STARTED) { - self.state = RUNNING; - self.timer.restart(tick, self.delay, self.time); - tick(elapsed); - } - }); - - // Dispatch the start event. - // Note this must be done before the tween are initialized. - self.state = STARTING; - self.on.call("start", node, node.__data__, self.index, self.group); - if (self.state !== STARTING) return; // interrupted - self.state = STARTED; - - // Initialize the tween, deleting null tween. - tween = new Array(n = self.tween.length); - for (i = 0, j = -1; i < n; ++i) { - if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { - tween[++j] = o; - } - } - tween.length = j + 1; - } - - function tick(elapsed) { - var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), - i = -1, - n = tween.length; - - while (++i < n) { - tween[i].call(node, t); - } - - // Dispatch the end event. - if (self.state === ENDING) { - self.on.call("end", node, node.__data__, self.index, self.group); - stop(); - } - } - - function stop() { - self.state = ENDED; - self.timer.stop(); - delete schedules[id]; - for (var i in schedules) return; // eslint-disable-line no-unused-vars - delete node.__transition; - } - } - - function interrupt(node, name) { - var schedules = node.__transition, - schedule, - active, - empty = true, - i; - - if (!schedules) return; - - name = name == null ? null : name + ""; - - for (i in schedules) { - if ((schedule = schedules[i]).name !== name) { empty = false; continue; } - active = schedule.state > STARTING && schedule.state < ENDING; - schedule.state = ENDED; - schedule.timer.stop(); - schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group); - delete schedules[i]; - } - - if (empty) delete node.__transition; - } - - function selection_interrupt(name) { - return this.each(function() { - interrupt(this, name); - }); - } - - function tweenRemove(id, name) { - var tween0, tween1; - return function() { - var schedule = set(this, id), - tween = schedule.tween; - - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = tween0 = tween; - for (var i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1 = tween1.slice(); - tween1.splice(i, 1); - break; - } - } - } - - schedule.tween = tween1; - }; - } - - function tweenFunction(id, name, value) { - var tween0, tween1; - if (typeof value !== "function") throw new Error; - return function() { - var schedule = set(this, id), - tween = schedule.tween; - - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = (tween0 = tween).slice(); - for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1[i] = t; - break; - } - } - if (i === n) tween1.push(t); - } - - schedule.tween = tween1; - }; - } - - function transition_tween(name, value) { - var id = this._id; - - name += ""; - - if (arguments.length < 2) { - var tween = get(this.node(), id).tween; - for (var i = 0, n = tween.length, t; i < n; ++i) { - if ((t = tween[i]).name === name) { - return t.value; - } - } - return null; - } - - return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); - } - - function tweenValue(transition, name, value) { - var id = transition._id; - - transition.each(function() { - var schedule = set(this, id); - (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); - }); - - return function(node) { - return get(node, id).value[name]; - }; - } - - function interpolate(a, b) { - var c; - return (typeof b === "number" ? interpolateNumber - : b instanceof color ? interpolateRgb - : (c = color(b)) ? (b = c, interpolateRgb) - : interpolateString)(a, b); - } - - function attrRemove(name) { - return function() { - this.removeAttribute(name); - }; - } - - function attrRemoveNS(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); - }; - } - - function attrConstant(name, interpolate, value1) { - var string00, - string1 = value1 + "", - interpolate0; - return function() { - var string0 = this.getAttribute(name); - return string0 === string1 ? null - : string0 === string00 ? interpolate0 - : interpolate0 = interpolate(string00 = string0, value1); - }; - } - - function attrConstantNS(fullname, interpolate, value1) { - var string00, - string1 = value1 + "", - interpolate0; - return function() { - var string0 = this.getAttributeNS(fullname.space, fullname.local); - return string0 === string1 ? null - : string0 === string00 ? interpolate0 - : interpolate0 = interpolate(string00 = string0, value1); - }; - } - - function attrFunction(name, interpolate, value) { - var string00, - string10, - interpolate0; - return function() { - var string0, value1 = value(this), string1; - if (value1 == null) return void this.removeAttribute(name); - string0 = this.getAttribute(name); - string1 = value1 + ""; - return string0 === string1 ? null - : string0 === string00 && string1 === string10 ? interpolate0 - : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); - }; - } - - function attrFunctionNS(fullname, interpolate, value) { - var string00, - string10, - interpolate0; - return function() { - var string0, value1 = value(this), string1; - if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); - string0 = this.getAttributeNS(fullname.space, fullname.local); - string1 = value1 + ""; - return string0 === string1 ? null - : string0 === string00 && string1 === string10 ? interpolate0 - : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); - }; - } - - function transition_attr(name, value) { - var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate; - return this.attrTween(name, typeof value === "function" - ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) - : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) - : (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value)); - } - - function attrInterpolate(name, i) { - return function(t) { - this.setAttribute(name, i.call(this, t)); - }; - } - - function attrInterpolateNS(fullname, i) { - return function(t) { - this.setAttributeNS(fullname.space, fullname.local, i.call(this, t)); - }; - } - - function attrTweenNS(fullname, value) { - var t0, i0; - function tween() { - var i = value.apply(this, arguments); - if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i); - return t0; - } - tween._value = value; - return tween; - } - - function attrTween(name, value) { - var t0, i0; - function tween() { - var i = value.apply(this, arguments); - if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i); - return t0; - } - tween._value = value; - return tween; - } - - function transition_attrTween(name, value) { - var key = "attr." + name; - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - var fullname = namespace(name); - return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); - } - - function delayFunction(id, value) { - return function() { - init(this, id).delay = +value.apply(this, arguments); - }; - } - - function delayConstant(id, value) { - return value = +value, function() { - init(this, id).delay = value; - }; - } - - function transition_delay(value) { - var id = this._id; - - return arguments.length - ? this.each((typeof value === "function" - ? delayFunction - : delayConstant)(id, value)) - : get(this.node(), id).delay; - } - - function durationFunction(id, value) { - return function() { - set(this, id).duration = +value.apply(this, arguments); - }; - } - - function durationConstant(id, value) { - return value = +value, function() { - set(this, id).duration = value; - }; - } - - function transition_duration(value) { - var id = this._id; - - return arguments.length - ? this.each((typeof value === "function" - ? durationFunction - : durationConstant)(id, value)) - : get(this.node(), id).duration; - } - - function easeConstant(id, value) { - if (typeof value !== "function") throw new Error; - return function() { - set(this, id).ease = value; - }; - } - - function transition_ease(value) { - var id = this._id; - - return arguments.length - ? this.each(easeConstant(id, value)) - : get(this.node(), id).ease; - } - - function easeVarying(id, value) { - return function() { - var v = value.apply(this, arguments); - if (typeof v !== "function") throw new Error; - set(this, id).ease = v; - }; - } - - function transition_easeVarying(value) { - if (typeof value !== "function") throw new Error; - return this.each(easeVarying(this._id, value)); - } - - function transition_filter(match) { - if (typeof match !== "function") match = matcher(match); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } - - return new Transition(subgroups, this._parents, this._name, this._id); - } - - function transition_merge(transition) { - if (transition._id !== this._id) throw new Error; - - for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } - } - - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } - - return new Transition(merges, this._parents, this._name, this._id); - } - - function start(name) { - return (name + "").trim().split(/^|\s+/).every(function(t) { - var i = t.indexOf("."); - if (i >= 0) t = t.slice(0, i); - return !t || t === "start"; - }); - } - - function onFunction(id, name, listener) { - var on0, on1, sit = start(name) ? init : set; - return function() { - var schedule = sit(this, id), - on = schedule.on; - - // If this node shared a dispatch with the previous node, - // just assign the updated shared dispatch and we’re done! - // Otherwise, copy-on-write. - if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); - - schedule.on = on1; - }; - } - - function transition_on(name, listener) { - var id = this._id; - - return arguments.length < 2 - ? get(this.node(), id).on.on(name) - : this.each(onFunction(id, name, listener)); - } - - function removeFunction(id) { - return function() { - var parent = this.parentNode; - for (var i in this.__transition) if (+i !== id) return; - if (parent) parent.removeChild(this); - }; - } - - function transition_remove() { - return this.on("end.remove", removeFunction(this._id)); - } - - function transition_select(select) { - var name = this._name, - id = this._id; - - if (typeof select !== "function") select = selector(select); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; - schedule(subgroup[i], name, id, i, subgroup, get(node, id)); - } - } - } - - return new Transition(subgroups, this._parents, name, id); - } - - function transition_selectAll(select) { - var name = this._name, - id = this._id; - - if (typeof select !== "function") select = selectorAll(select); - - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - for (var children = select.call(node, node.__data__, i, group), child, inherit = get(node, id), k = 0, l = children.length; k < l; ++k) { - if (child = children[k]) { - schedule(child, name, id, k, children, inherit); - } - } - subgroups.push(children); - parents.push(node); - } - } - } - - return new Transition(subgroups, parents, name, id); - } - - var Selection = selection.prototype.constructor; - - function transition_selection() { - return new Selection(this._groups, this._parents); - } - - function styleNull(name, interpolate) { - var string00, - string10, - interpolate0; - return function() { - var string0 = styleValue(this, name), - string1 = (this.style.removeProperty(name), styleValue(this, name)); - return string0 === string1 ? null - : string0 === string00 && string1 === string10 ? interpolate0 - : interpolate0 = interpolate(string00 = string0, string10 = string1); - }; - } - - function styleRemove(name) { - return function() { - this.style.removeProperty(name); - }; - } - - function styleConstant(name, interpolate, value1) { - var string00, - string1 = value1 + "", - interpolate0; - return function() { - var string0 = styleValue(this, name); - return string0 === string1 ? null - : string0 === string00 ? interpolate0 - : interpolate0 = interpolate(string00 = string0, value1); - }; - } - - function styleFunction(name, interpolate, value) { - var string00, - string10, - interpolate0; - return function() { - var string0 = styleValue(this, name), - value1 = value(this), - string1 = value1 + ""; - if (value1 == null) string1 = value1 = (this.style.removeProperty(name), styleValue(this, name)); - return string0 === string1 ? null - : string0 === string00 && string1 === string10 ? interpolate0 - : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); - }; - } - - function styleMaybeRemove(id, name) { - var on0, on1, listener0, key = "style." + name, event = "end." + key, remove; - return function() { - var schedule = set(this, id), - on = schedule.on, - listener = schedule.value[key] == null ? remove || (remove = styleRemove(name)) : undefined; - - // If this node shared a dispatch with the previous node, - // just assign the updated shared dispatch and we’re done! - // Otherwise, copy-on-write. - if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener); - - schedule.on = on1; - }; - } - - function transition_style(name, value, priority) { - var i = (name += "") === "transform" ? interpolateTransformCss : interpolate; - return value == null ? this - .styleTween(name, styleNull(name, i)) - .on("end.style." + name, styleRemove(name)) - : typeof value === "function" ? this - .styleTween(name, styleFunction(name, i, tweenValue(this, "style." + name, value))) - .each(styleMaybeRemove(this._id, name)) - : this - .styleTween(name, styleConstant(name, i, value), priority) - .on("end.style." + name, null); - } - - function styleInterpolate(name, i, priority) { - return function(t) { - this.style.setProperty(name, i.call(this, t), priority); - }; - } - - function styleTween(name, value, priority) { - var t, i0; - function tween() { - var i = value.apply(this, arguments); - if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority); - return t; - } - tween._value = value; - return tween; - } - - function transition_styleTween(name, value, priority) { - var key = "style." + (name += ""); - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); - } - - function textConstant(value) { - return function() { - this.textContent = value; - }; - } - - function textFunction(value) { - return function() { - var value1 = value(this); - this.textContent = value1 == null ? "" : value1; - }; - } - - function transition_text(value) { - return this.tween("text", typeof value === "function" - ? textFunction(tweenValue(this, "text", value)) - : textConstant(value == null ? "" : value + "")); - } - - function textInterpolate(i) { - return function(t) { - this.textContent = i.call(this, t); - }; - } - - function textTween(value) { - var t0, i0; - function tween() { - var i = value.apply(this, arguments); - if (i !== i0) t0 = (i0 = i) && textInterpolate(i); - return t0; - } - tween._value = value; - return tween; - } - - function transition_textTween(value) { - var key = "text"; - if (arguments.length < 1) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - return this.tween(key, textTween(value)); - } - - function transition_transition() { - var name = this._name, - id0 = this._id, - id1 = newId(); - - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - var inherit = get(node, id0); - schedule(node, name, id1, i, group, { - time: inherit.time + inherit.delay + inherit.duration, - delay: 0, - duration: inherit.duration, - ease: inherit.ease - }); - } - } - } - - return new Transition(groups, this._parents, name, id1); - } - - function transition_end() { - var on0, on1, that = this, id = that._id, size = that.size(); - return new Promise(function(resolve, reject) { - var cancel = {value: reject}, - end = {value: function() { if (--size === 0) resolve(); }}; - - that.each(function() { - var schedule = set(this, id), - on = schedule.on; - - // If this node shared a dispatch with the previous node, - // just assign the updated shared dispatch and we’re done! - // Otherwise, copy-on-write. - if (on !== on0) { - on1 = (on0 = on).copy(); - on1._.cancel.push(cancel); - on1._.interrupt.push(cancel); - on1._.end.push(end); - } - - schedule.on = on1; - }); - - // The selection was empty, resolve end immediately - if (size === 0) resolve(); - }); - } - - var id = 0; - - function Transition(groups, parents, name, id) { - this._groups = groups; - this._parents = parents; - this._name = name; - this._id = id; - } - - function newId() { - return ++id; - } - - var selection_prototype = selection.prototype; - - Transition.prototype = { - constructor: Transition, - select: transition_select, - selectAll: transition_selectAll, - selectChild: selection_prototype.selectChild, - selectChildren: selection_prototype.selectChildren, - filter: transition_filter, - merge: transition_merge, - selection: transition_selection, - transition: transition_transition, - call: selection_prototype.call, - nodes: selection_prototype.nodes, - node: selection_prototype.node, - size: selection_prototype.size, - empty: selection_prototype.empty, - each: selection_prototype.each, - on: transition_on, - attr: transition_attr, - attrTween: transition_attrTween, - style: transition_style, - styleTween: transition_styleTween, - text: transition_text, - textTween: transition_textTween, - remove: transition_remove, - tween: transition_tween, - delay: transition_delay, - duration: transition_duration, - ease: transition_ease, - easeVarying: transition_easeVarying, - end: transition_end, - [Symbol.iterator]: selection_prototype[Symbol.iterator] - }; - - function cubicInOut(t) { - return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; - } - - var defaultTiming = { - time: null, // Set on use. - delay: 0, - duration: 250, - ease: cubicInOut - }; - - function inherit(node, id) { - var timing; - while (!(timing = node.__transition) || !(timing = timing[id])) { - if (!(node = node.parentNode)) { - throw new Error(`transition ${id} not found`); - } - } - return timing; - } - - function selection_transition(name) { - var id, - timing; - - if (name instanceof Transition) { - id = name._id, name = name._name; - } else { - id = newId(), (timing = defaultTiming).time = now$3(), name = name == null ? null : name + ""; - } - - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - schedule(node, name, id, i, group, timing || inherit(node, id)); - } - } - } - - return new Transition(groups, this._parents, name, id); - } - - selection.prototype.interrupt = selection_interrupt; - selection.prototype.transition = selection_transition; - - var constant$1 = x => () => x; - - function ZoomEvent(type, { - sourceEvent, - target, - transform, - dispatch - }) { - Object.defineProperties(this, { - type: {value: type, enumerable: true, configurable: true}, - sourceEvent: {value: sourceEvent, enumerable: true, configurable: true}, - target: {value: target, enumerable: true, configurable: true}, - transform: {value: transform, enumerable: true, configurable: true}, - _: {value: dispatch} - }); - } - - function Transform(k, x, y) { - this.k = k; - this.x = x; - this.y = y; - } - - Transform.prototype = { - constructor: Transform, - scale: function(k) { - return k === 1 ? this : new Transform(this.k * k, this.x, this.y); - }, - translate: function(x, y) { - return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); - }, - apply: function(point) { - return [point[0] * this.k + this.x, point[1] * this.k + this.y]; - }, - applyX: function(x) { - return x * this.k + this.x; - }, - applyY: function(y) { - return y * this.k + this.y; - }, - invert: function(location) { - return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; - }, - invertX: function(x) { - return (x - this.x) / this.k; - }, - invertY: function(y) { - return (y - this.y) / this.k; - }, - rescaleX: function(x) { - return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); - }, - rescaleY: function(y) { - return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); - }, - toString: function() { - return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; - } - }; - - var identity = new Transform(1, 0, 0); - - transform.prototype = Transform.prototype; - - function transform(node) { - while (!node.__zoom) if (!(node = node.parentNode)) return identity; - return node.__zoom; - } - - function nopropagation(event) { - event.stopImmediatePropagation(); - } - - function noevent(event) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - - // Ignore right-click, since that should open the context menu. - // except for pinch-to-zoom, which is sent as a wheel+ctrlKey event - function defaultFilter(event) { - return (!event.ctrlKey || event.type === 'wheel') && !event.button; - } - - function defaultExtent() { - var e = this; - if (e instanceof SVGElement) { - e = e.ownerSVGElement || e; - if (e.hasAttribute("viewBox")) { - e = e.viewBox.baseVal; - return [[e.x, e.y], [e.x + e.width, e.y + e.height]]; - } - return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]]; - } - return [[0, 0], [e.clientWidth, e.clientHeight]]; - } - - function defaultTransform() { - return this.__zoom || identity; - } - - function defaultWheelDelta(event) { - return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * (event.ctrlKey ? 10 : 1); - } - - function defaultTouchable() { - return navigator.maxTouchPoints || ("ontouchstart" in this); - } - - function defaultConstrain(transform, extent, translateExtent) { - var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0], - dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0], - dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1], - dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1]; - return transform.translate( - dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), - dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) - ); - } - - function d3Zoom() { - var filter = defaultFilter, - extent = defaultExtent, - constrain = defaultConstrain, - wheelDelta = defaultWheelDelta, - touchable = defaultTouchable, - scaleExtent = [0, Infinity], - translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], - duration = 250, - interpolate = interpolateZoom, - listeners = dispatch("start", "zoom", "end"), - touchstarting, - touchfirst, - touchending, - touchDelay = 500, - wheelDelay = 150, - clickDistance2 = 0, - tapDistance = 10; - - function zoom(selection) { - selection - .property("__zoom", defaultTransform) - .on("wheel.zoom", wheeled, {passive: false}) - .on("mousedown.zoom", mousedowned) - .on("dblclick.zoom", dblclicked) - .filter(touchable) - .on("touchstart.zoom", touchstarted) - .on("touchmove.zoom", touchmoved) - .on("touchend.zoom touchcancel.zoom", touchended) - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); - } - - zoom.transform = function(collection, transform, point, event) { - var selection = collection.selection ? collection.selection() : collection; - selection.property("__zoom", defaultTransform); - if (collection !== selection) { - schedule(collection, transform, point, event); - } else { - selection.interrupt().each(function() { - gesture(this, arguments) - .event(event) - .start() - .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform) - .end(); - }); - } - }; - - zoom.scaleBy = function(selection, k, p, event) { - zoom.scaleTo(selection, function() { - var k0 = this.__zoom.k, - k1 = typeof k === "function" ? k.apply(this, arguments) : k; - return k0 * k1; - }, p, event); - }; - - zoom.scaleTo = function(selection, k, p, event) { - zoom.transform(selection, function() { - var e = extent.apply(this, arguments), - t0 = this.__zoom, - p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p, - p1 = t0.invert(p0), - k1 = typeof k === "function" ? k.apply(this, arguments) : k; - return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent); - }, p, event); - }; - - zoom.translateBy = function(selection, x, y, event) { - zoom.transform(selection, function() { - return constrain(this.__zoom.translate( - typeof x === "function" ? x.apply(this, arguments) : x, - typeof y === "function" ? y.apply(this, arguments) : y - ), extent.apply(this, arguments), translateExtent); - }, null, event); - }; - - zoom.translateTo = function(selection, x, y, p, event) { - zoom.transform(selection, function() { - var e = extent.apply(this, arguments), - t = this.__zoom, - p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p; - return constrain(identity.translate(p0[0], p0[1]).scale(t.k).translate( - typeof x === "function" ? -x.apply(this, arguments) : -x, - typeof y === "function" ? -y.apply(this, arguments) : -y - ), e, translateExtent); - }, p, event); - }; - - function scale(transform, k) { - k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k)); - return k === transform.k ? transform : new Transform(k, transform.x, transform.y); - } - - function translate(transform, p0, p1) { - var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k; - return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y); - } - - function centroid(extent) { - return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; - } - - function schedule(transition, transform, point, event) { - transition - .on("start.zoom", function() { gesture(this, arguments).event(event).start(); }) - .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).event(event).end(); }) - .tween("zoom", function() { - var that = this, - args = arguments, - g = gesture(that, args).event(event), - e = extent.apply(that, args), - p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point, - w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), - a = that.__zoom, - b = typeof transform === "function" ? transform.apply(that, args) : transform, - i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); - return function(t) { - if (t === 1) t = b; // Avoid rounding error on end. - else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } - g.zoom(null, t); - }; - }); - } - - function gesture(that, args, clean) { - return (!clean && that.__zooming) || new Gesture(that, args); - } - - function Gesture(that, args) { - this.that = that; - this.args = args; - this.active = 0; - this.sourceEvent = null; - this.extent = extent.apply(that, args); - this.taps = 0; - } - - Gesture.prototype = { - event: function(event) { - if (event) this.sourceEvent = event; - return this; - }, - start: function() { - if (++this.active === 1) { - this.that.__zooming = this; - this.emit("start"); - } - return this; - }, - zoom: function(key, transform) { - if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]); - if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]); - if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]); - this.that.__zoom = transform; - this.emit("zoom"); - return this; - }, - end: function() { - if (--this.active === 0) { - delete this.that.__zooming; - this.emit("end"); - } - return this; - }, - emit: function(type) { - var d = d3Select(this.that).datum(); - listeners.call( - type, - this.that, - new ZoomEvent(type, { - sourceEvent: this.sourceEvent, - target: zoom, - type, - transform: this.that.__zoom, - dispatch: listeners - }), - d - ); - } - }; - - function wheeled(event, ...args) { - if (!filter.apply(this, arguments)) return; - var g = gesture(this, args).event(event), - t = this.__zoom, - k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), - p = pointer(event); - - // If the mouse is in the same location as before, reuse it. - // If there were recent wheel events, reset the wheel idle timeout. - if (g.wheel) { - if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { - g.mouse[1] = t.invert(g.mouse[0] = p); - } - clearTimeout(g.wheel); - } - - // If this wheel event won’t trigger a transform change, ignore it. - else if (t.k === k) return; - - // Otherwise, capture the mouse point and location at the start. - else { - g.mouse = [p, t.invert(p)]; - interrupt(this); - g.start(); - } - - noevent(event); - g.wheel = setTimeout(wheelidled, wheelDelay); - g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent)); - - function wheelidled() { - g.wheel = null; - g.end(); - } - } - - function mousedowned(event, ...args) { - if (touchending || !filter.apply(this, arguments)) return; - var currentTarget = event.currentTarget, - g = gesture(this, args, true).event(event), - v = d3Select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), - p = pointer(event, currentTarget), - x0 = event.clientX, - y0 = event.clientY; - - dragDisable(event.view); - nopropagation(event); - g.mouse = [p, this.__zoom.invert(p)]; - interrupt(this); - g.start(); - - function mousemoved(event) { - noevent(event); - if (!g.moved) { - var dx = event.clientX - x0, dy = event.clientY - y0; - g.moved = dx * dx + dy * dy > clickDistance2; - } - g.event(event) - .zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = pointer(event, currentTarget), g.mouse[1]), g.extent, translateExtent)); - } - - function mouseupped(event) { - v.on("mousemove.zoom mouseup.zoom", null); - yesdrag(event.view, g.moved); - noevent(event); - g.event(event).end(); - } - } - - function dblclicked(event, ...args) { - if (!filter.apply(this, arguments)) return; - var t0 = this.__zoom, - p0 = pointer(event.changedTouches ? event.changedTouches[0] : event, this), - p1 = t0.invert(p0), - k1 = t0.k * (event.shiftKey ? 0.5 : 2), - t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, args), translateExtent); - - noevent(event); - if (duration > 0) d3Select(this).transition().duration(duration).call(schedule, t1, p0, event); - else d3Select(this).call(zoom.transform, t1, p0, event); - } - - function touchstarted(event, ...args) { - if (!filter.apply(this, arguments)) return; - var touches = event.touches, - n = touches.length, - g = gesture(this, args, event.changedTouches.length === n).event(event), - started, i, t, p; - - nopropagation(event); - for (i = 0; i < n; ++i) { - t = touches[i], p = pointer(t, this); - p = [p, this.__zoom.invert(p), t.identifier]; - if (!g.touch0) g.touch0 = p, started = true, g.taps = 1 + !!touchstarting; - else if (!g.touch1 && g.touch0[2] !== p[2]) g.touch1 = p, g.taps = 0; - } - - if (touchstarting) touchstarting = clearTimeout(touchstarting); - - if (started) { - if (g.taps < 2) touchfirst = p[0], touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); - interrupt(this); - g.start(); - } - } - - function touchmoved(event, ...args) { - if (!this.__zooming) return; - var g = gesture(this, args).event(event), - touches = event.changedTouches, - n = touches.length, i, t, p, l; - - noevent(event); - for (i = 0; i < n; ++i) { - t = touches[i], p = pointer(t, this); - if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; - else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; - } - t = g.that.__zoom; - if (g.touch1) { - var p0 = g.touch0[0], l0 = g.touch0[1], - p1 = g.touch1[0], l1 = g.touch1[1], - dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, - dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; - t = scale(t, Math.sqrt(dp / dl)); - p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; - l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; - } - else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; - else return; - - g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent)); - } - - function touchended(event, ...args) { - if (!this.__zooming) return; - var g = gesture(this, args).event(event), - touches = event.changedTouches, - n = touches.length, i, t; - - nopropagation(event); - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, touchDelay); - for (i = 0; i < n; ++i) { - t = touches[i]; - if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; - else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; - } - if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; - if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]); - else { - g.end(); - // If this was a dbltap, reroute to the (optional) dblclick.zoom handler. - if (g.taps === 2) { - t = pointer(t, this); - if (Math.hypot(touchfirst[0] - t[0], touchfirst[1] - t[1]) < tapDistance) { - var p = d3Select(this).on("dblclick.zoom"); - if (p) p.apply(this, arguments); - } - } - } - } - - zoom.wheelDelta = function(_) { - return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant$1(+_), zoom) : wheelDelta; - }; - - zoom.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$1(!!_), zoom) : filter; - }; - - zoom.touchable = function(_) { - return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$1(!!_), zoom) : touchable; - }; - - zoom.extent = function(_) { - return arguments.length ? (extent = typeof _ === "function" ? _ : constant$1([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; - }; - - zoom.scaleExtent = function(_) { - return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]]; - }; - - zoom.translateExtent = function(_) { - return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]]; - }; - - zoom.constrain = function(_) { - return arguments.length ? (constrain = _, zoom) : constrain; - }; - - zoom.duration = function(_) { - return arguments.length ? (duration = +_, zoom) : duration; - }; - - zoom.interpolate = function(_) { - return arguments.length ? (interpolate = _, zoom) : interpolate; - }; - - zoom.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? zoom : value; - }; - - zoom.clickDistance = function(_) { - return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2); - }; - - zoom.tapDistance = function(_) { - return arguments.length ? (tapDistance = +_, zoom) : tapDistance; - }; - - return zoom; - } - - class InternMap extends Map { - constructor(entries, key = keyof) { - super(); - Object.defineProperties(this, {_intern: {value: new Map()}, _key: {value: key}}); - if (entries != null) for (const [key, value] of entries) this.set(key, value); - } - get(key) { - return super.get(intern_get(this, key)); - } - has(key) { - return super.has(intern_get(this, key)); - } - set(key, value) { - return super.set(intern_set(this, key), value); - } - delete(key) { - return super.delete(intern_delete(this, key)); - } - } - - function intern_get({_intern, _key}, value) { - const key = _key(value); - return _intern.has(key) ? _intern.get(key) : value; - } - - function intern_set({_intern, _key}, value) { - const key = _key(value); - if (_intern.has(key)) return _intern.get(key); - _intern.set(key, value); - return value; - } - - function intern_delete({_intern, _key}, value) { - const key = _key(value); - if (_intern.has(key)) { - value = _intern.get(key); - _intern.delete(key); - } - return value; - } - - function keyof(value) { - return value !== null && typeof value === "object" ? value.valueOf() : value; - } - - function max$1(values, valueof) { - let max; - if (valueof === undefined) { - for (const value of values) { - if (value != null - && (max < value || (max === undefined && value >= value))) { - max = value; - } - } - } else { - let index = -1; - for (let value of values) { - if ((value = valueof(value, ++index, values)) != null - && (max < value || (max === undefined && value >= value))) { - max = value; - } - } - } - return max; - } - - function min$1(values, valueof) { - let min; - if (valueof === undefined) { - for (const value of values) { - if (value != null - && (min > value || (min === undefined && value >= value))) { - min = value; - } - } - } else { - let index = -1; - for (let value of values) { - if ((value = valueof(value, ++index, values)) != null - && (min > value || (min === undefined && value >= value))) { - min = value; - } - } - } - return min; - } - - /** Detect free variable `global` from Node.js. */ - var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; - - var freeGlobal$1 = freeGlobal; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root = freeGlobal$1 || freeSelf || Function('return this')(); - - var root$1 = root; - - /** Built-in value references. */ - var Symbol$1 = root$1.Symbol; - - var Symbol$2 = Symbol$1; - - /** Used for built-in method references. */ - var objectProto$1 = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto$1.hasOwnProperty; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString$1 = objectProto$1.toString; - - /** Built-in value references. */ - var symToStringTag$1 = Symbol$2 ? Symbol$2.toStringTag : undefined; - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag$1), - tag = value[symToStringTag$1]; - - try { - value[symToStringTag$1] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString$1.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$1] = tag; - } else { - delete value[symToStringTag$1]; - } - } - return result; - } - - /** Used for built-in method references. */ - var objectProto = Object.prototype; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString(value) { - return nativeObjectToString.call(value); - } - - /** `Object#toString` result references. */ - var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - - /** Built-in value references. */ - var symToStringTag = Symbol$2 ? Symbol$2.toStringTag : undefined; - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); - } - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - function isObjectLike(value) { - return value != null && typeof value == 'object'; - } - - /** `Object#toString` result references. */ - var symbolTag = '[object Symbol]'; - - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); - } - - /** Used to match a single whitespace character. */ - var reWhitespace = /\s/; - - /** - * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the last non-whitespace character. - */ - function trimmedEndIndex(string) { - var index = string.length; - - while (index-- && reWhitespace.test(string.charAt(index))) {} - return index; - } - - /** Used to match leading whitespace. */ - var reTrimStart = /^\s+/; - - /** - * The base implementation of `_.trim`. - * - * @private - * @param {string} string The string to trim. - * @returns {string} Returns the trimmed string. - */ - function baseTrim(string) { - return string - ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') - : string; - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - function isObject(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - /** Used as references for various `Number` constants. */ - var NAN = 0 / 0; - - /** Used to detect bad signed hexadecimal string values. */ - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - - /** Used to detect binary string values. */ - var reIsBinary = /^0b[01]+$/i; - - /** Used to detect octal string values. */ - var reIsOctal = /^0o[0-7]+$/i; - - /** Built-in method references without a dependency on `root`. */ - var freeParseInt = parseInt; - - /** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ - function toNumber(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = baseTrim(value); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); - } - - /** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ - var now$1 = function() { - return root$1.Date.now(); - }; - - var now$2 = now$1; - - /** Error message constants. */ - var FUNC_ERROR_TEXT$1 = 'Expected a function'; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max, - nativeMin = Math.min; - - /** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. Subsequent - * calls to the debounced function return the result of the last `func` - * invocation. - * - * **Note:** If `leading` and `trailing` options are `true`, `func` is - * invoked on the trailing edge of the timeout only if the debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to debounce. - * @param {number} [wait=0] The number of milliseconds to delay. - * @param {Object} [options={}] The options object. - * @param {boolean} [options.leading=false] - * Specify invoking on the leading edge of the timeout. - * @param {number} [options.maxWait] - * The maximum time `func` is allowed to be delayed before it's invoked. - * @param {boolean} [options.trailing=true] - * Specify invoking on the trailing edge of the timeout. - * @returns {Function} Returns the new debounced function. - * @example - * - * // Avoid costly calculations while the window size is in flux. - * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); - * - * // Invoke `sendMail` when clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ - function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT$1); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - timeWaiting = wait - timeSinceLastCall; - - return maxing - ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now$2(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now$2()); - } - - function debounced() { - var time = now$2(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - clearTimeout(timerId); - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - - /** Error message constants. */ - var FUNC_ERROR_TEXT = 'Expected a function'; - - /** - * Creates a throttled function that only invokes `func` at most once per - * every `wait` milliseconds. The throttled function comes with a `cancel` - * method to cancel delayed `func` invocations and a `flush` method to - * immediately invoke them. Provide `options` to indicate whether `func` - * should be invoked on the leading and/or trailing edge of the `wait` - * timeout. The `func` is invoked with the last arguments provided to the - * throttled function. Subsequent calls to the throttled function return the - * result of the last `func` invocation. - * - * **Note:** If `leading` and `trailing` options are `true`, `func` is - * invoked on the trailing edge of the timeout only if the throttled function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.throttle` and `_.debounce`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to throttle. - * @param {number} [wait=0] The number of milliseconds to throttle invocations to. - * @param {Object} [options={}] The options object. - * @param {boolean} [options.leading=true] - * Specify invoking on the leading edge of the timeout. - * @param {boolean} [options.trailing=true] - * Specify invoking on the trailing edge of the timeout. - * @returns {Function} Returns the new throttled function. - * @example - * - * // Avoid excessively updating the position while scrolling. - * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); - * - * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. - * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); - * jQuery(element).on('click', throttled); - * - * // Cancel the trailing throttled invocation. - * jQuery(window).on('popstate', throttled.cancel); - */ - function throttle(func, wait, options) { - var leading = true, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - if (isObject(options)) { - leading = 'leading' in options ? !!options.leading : leading; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - return debounce(func, wait, { - 'leading': leading, - 'maxWait': wait, - 'trailing': trailing - }); - } - - /** - * The Ease class provides a collection of easing functions for use with tween.js. - */ - var Easing = Object.freeze({ - Linear: Object.freeze({ - None: function (amount) { - return amount; - }, - In: function (amount) { - return this.None(amount); - }, - Out: function (amount) { - return this.None(amount); - }, - InOut: function (amount) { - return this.None(amount); - }, - }), - Quadratic: Object.freeze({ - In: function (amount) { - return amount * amount; - }, - Out: function (amount) { - return amount * (2 - amount); - }, - InOut: function (amount) { - if ((amount *= 2) < 1) { - return 0.5 * amount * amount; - } - return -0.5 * (--amount * (amount - 2) - 1); - }, - }), - Cubic: Object.freeze({ - In: function (amount) { - return amount * amount * amount; - }, - Out: function (amount) { - return --amount * amount * amount + 1; - }, - InOut: function (amount) { - if ((amount *= 2) < 1) { - return 0.5 * amount * amount * amount; - } - return 0.5 * ((amount -= 2) * amount * amount + 2); - }, - }), - Quartic: Object.freeze({ - In: function (amount) { - return amount * amount * amount * amount; - }, - Out: function (amount) { - return 1 - --amount * amount * amount * amount; - }, - InOut: function (amount) { - if ((amount *= 2) < 1) { - return 0.5 * amount * amount * amount * amount; - } - return -0.5 * ((amount -= 2) * amount * amount * amount - 2); - }, - }), - Quintic: Object.freeze({ - In: function (amount) { - return amount * amount * amount * amount * amount; - }, - Out: function (amount) { - return --amount * amount * amount * amount * amount + 1; - }, - InOut: function (amount) { - if ((amount *= 2) < 1) { - return 0.5 * amount * amount * amount * amount * amount; - } - return 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2); - }, - }), - Sinusoidal: Object.freeze({ - In: function (amount) { - return 1 - Math.sin(((1.0 - amount) * Math.PI) / 2); - }, - Out: function (amount) { - return Math.sin((amount * Math.PI) / 2); - }, - InOut: function (amount) { - return 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount))); - }, - }), - Exponential: Object.freeze({ - In: function (amount) { - return amount === 0 ? 0 : Math.pow(1024, amount - 1); - }, - Out: function (amount) { - return amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount); - }, - InOut: function (amount) { - if (amount === 0) { - return 0; - } - if (amount === 1) { - return 1; - } - if ((amount *= 2) < 1) { - return 0.5 * Math.pow(1024, amount - 1); - } - return 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2); - }, - }), - Circular: Object.freeze({ - In: function (amount) { - return 1 - Math.sqrt(1 - amount * amount); - }, - Out: function (amount) { - return Math.sqrt(1 - --amount * amount); - }, - InOut: function (amount) { - if ((amount *= 2) < 1) { - return -0.5 * (Math.sqrt(1 - amount * amount) - 1); - } - return 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1); - }, - }), - Elastic: Object.freeze({ - In: function (amount) { - if (amount === 0) { - return 0; - } - if (amount === 1) { - return 1; - } - return -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI); - }, - Out: function (amount) { - if (amount === 0) { - return 0; - } - if (amount === 1) { - return 1; - } - return Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1; - }, - InOut: function (amount) { - if (amount === 0) { - return 0; - } - if (amount === 1) { - return 1; - } - amount *= 2; - if (amount < 1) { - return -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI); - } - return 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1; - }, - }), - Back: Object.freeze({ - In: function (amount) { - var s = 1.70158; - return amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s); - }, - Out: function (amount) { - var s = 1.70158; - return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1; - }, - InOut: function (amount) { - var s = 1.70158 * 1.525; - if ((amount *= 2) < 1) { - return 0.5 * (amount * amount * ((s + 1) * amount - s)); - } - return 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2); - }, - }), - Bounce: Object.freeze({ - In: function (amount) { - return 1 - Easing.Bounce.Out(1 - amount); - }, - Out: function (amount) { - if (amount < 1 / 2.75) { - return 7.5625 * amount * amount; - } - else if (amount < 2 / 2.75) { - return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75; - } - else if (amount < 2.5 / 2.75) { - return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375; - } - else { - return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375; - } - }, - InOut: function (amount) { - if (amount < 0.5) { - return Easing.Bounce.In(amount * 2) * 0.5; - } - return Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5; - }, - }), - generatePow: function (power) { - if (power === void 0) { power = 4; } - power = power < Number.EPSILON ? Number.EPSILON : power; - power = power > 10000 ? 10000 : power; - return { - In: function (amount) { - return Math.pow(amount, power); - }, - Out: function (amount) { - return 1 - Math.pow((1 - amount), power); - }, - InOut: function (amount) { - if (amount < 0.5) { - return Math.pow((amount * 2), power) / 2; - } - return (1 - Math.pow((2 - amount * 2), power)) / 2 + 0.5; - }, - }; - }, - }); - - var now = function () { return performance.now(); }; - - /** - * Controlling groups of tweens - * - * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components. - * In these cases, you may want to create your own smaller groups of tween - */ - var Group = /** @class */ (function () { - function Group() { - this._tweens = {}; - this._tweensAddedDuringUpdate = {}; - } - Group.prototype.getAll = function () { - var _this = this; - return Object.keys(this._tweens).map(function (tweenId) { - return _this._tweens[tweenId]; - }); - }; - Group.prototype.removeAll = function () { - this._tweens = {}; - }; - Group.prototype.add = function (tween) { - this._tweens[tween.getId()] = tween; - this._tweensAddedDuringUpdate[tween.getId()] = tween; - }; - Group.prototype.remove = function (tween) { - delete this._tweens[tween.getId()]; - delete this._tweensAddedDuringUpdate[tween.getId()]; - }; - Group.prototype.update = function (time, preserve) { - if (time === void 0) { time = now(); } - if (preserve === void 0) { preserve = false; } - var tweenIds = Object.keys(this._tweens); - if (tweenIds.length === 0) { - return false; - } - // Tweens are updated in "batches". If you add a new tween during an - // update, then the new tween will be updated in the next batch. - // If you remove a tween during an update, it may or may not be updated. - // However, if the removed tween was added during the current batch, - // then it will not be updated. - while (tweenIds.length > 0) { - this._tweensAddedDuringUpdate = {}; - for (var i = 0; i < tweenIds.length; i++) { - var tween = this._tweens[tweenIds[i]]; - var autoStart = !preserve; - if (tween && tween.update(time, autoStart) === false && !preserve) { - delete this._tweens[tweenIds[i]]; - } - } - tweenIds = Object.keys(this._tweensAddedDuringUpdate); - } - return true; - }; - return Group; - }()); - - /** - * - */ - var Interpolation = { - Linear: function (v, k) { - var m = v.length - 1; - var f = m * k; - var i = Math.floor(f); - var fn = Interpolation.Utils.Linear; - if (k < 0) { - return fn(v[0], v[1], f); - } - if (k > 1) { - return fn(v[m], v[m - 1], m - f); - } - return fn(v[i], v[i + 1 > m ? m : i + 1], f - i); - }, - Bezier: function (v, k) { - var b = 0; - var n = v.length - 1; - var pw = Math.pow; - var bn = Interpolation.Utils.Bernstein; - for (var i = 0; i <= n; i++) { - b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i); - } - return b; - }, - CatmullRom: function (v, k) { - var m = v.length - 1; - var f = m * k; - var i = Math.floor(f); - var fn = Interpolation.Utils.CatmullRom; - if (v[0] === v[m]) { - if (k < 0) { - i = Math.floor((f = m * (1 + k))); - } - return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i); - } - else { - if (k < 0) { - return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]); - } - if (k > 1) { - return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]); - } - return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i); - } - }, - Utils: { - Linear: function (p0, p1, t) { - return (p1 - p0) * t + p0; - }, - Bernstein: function (n, i) { - var fc = Interpolation.Utils.Factorial; - return fc(n) / fc(i) / fc(n - i); - }, - Factorial: (function () { - var a = [1]; - return function (n) { - var s = 1; - if (a[n]) { - return a[n]; - } - for (var i = n; i > 1; i--) { - s *= i; - } - a[n] = s; - return s; - }; - })(), - CatmullRom: function (p0, p1, p2, p3, t) { - var v0 = (p2 - p0) * 0.5; - var v1 = (p3 - p1) * 0.5; - var t2 = t * t; - var t3 = t * t2; - return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; - }, - }, - }; - - /** - * Utils - */ - var Sequence = /** @class */ (function () { - function Sequence() { - } - Sequence.nextId = function () { - return Sequence._nextId++; - }; - Sequence._nextId = 0; - return Sequence; - }()); - - var mainGroup = new Group(); - - /** - * Tween.js - Licensed under the MIT license - * https://github.com/tweenjs/tween.js - * ---------------------------------------------- - * - * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors. - * Thank you all, you're awesome! - */ - var Tween = /** @class */ (function () { - function Tween(_object, _group) { - if (_group === void 0) { _group = mainGroup; } - this._object = _object; - this._group = _group; - this._isPaused = false; - this._pauseStart = 0; - this._valuesStart = {}; - this._valuesEnd = {}; - this._valuesStartRepeat = {}; - this._duration = 1000; - this._isDynamic = false; - this._initialRepeat = 0; - this._repeat = 0; - this._yoyo = false; - this._isPlaying = false; - this._reversed = false; - this._delayTime = 0; - this._startTime = 0; - this._easingFunction = Easing.Linear.None; - this._interpolationFunction = Interpolation.Linear; - // eslint-disable-next-line - this._chainedTweens = []; - this._onStartCallbackFired = false; - this._onEveryStartCallbackFired = false; - this._id = Sequence.nextId(); - this._isChainStopped = false; - this._propertiesAreSetUp = false; - this._goToEnd = false; - } - Tween.prototype.getId = function () { - return this._id; - }; - Tween.prototype.isPlaying = function () { - return this._isPlaying; - }; - Tween.prototype.isPaused = function () { - return this._isPaused; - }; - Tween.prototype.to = function (target, duration) { - if (duration === void 0) { duration = 1000; } - if (this._isPlaying) - throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.'); - this._valuesEnd = target; - this._propertiesAreSetUp = false; - this._duration = duration; - return this; - }; - Tween.prototype.duration = function (duration) { - if (duration === void 0) { duration = 1000; } - this._duration = duration; - return this; - }; - Tween.prototype.dynamic = function (dynamic) { - if (dynamic === void 0) { dynamic = false; } - this._isDynamic = dynamic; - return this; - }; - Tween.prototype.start = function (time, overrideStartingValues) { - if (time === void 0) { time = now(); } - if (overrideStartingValues === void 0) { overrideStartingValues = false; } - if (this._isPlaying) { - return this; - } - // eslint-disable-next-line - this._group && this._group.add(this); - this._repeat = this._initialRepeat; - if (this._reversed) { - // If we were reversed (f.e. using the yoyo feature) then we need to - // flip the tween direction back to forward. - this._reversed = false; - for (var property in this._valuesStartRepeat) { - this._swapEndStartRepeatValues(property); - this._valuesStart[property] = this._valuesStartRepeat[property]; - } - } - this._isPlaying = true; - this._isPaused = false; - this._onStartCallbackFired = false; - this._onEveryStartCallbackFired = false; - this._isChainStopped = false; - this._startTime = time; - this._startTime += this._delayTime; - if (!this._propertiesAreSetUp || overrideStartingValues) { - this._propertiesAreSetUp = true; - // If dynamic is not enabled, clone the end values instead of using the passed-in end values. - if (!this._isDynamic) { - var tmp = {}; - for (var prop in this._valuesEnd) - tmp[prop] = this._valuesEnd[prop]; - this._valuesEnd = tmp; - } - this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, overrideStartingValues); - } - return this; - }; - Tween.prototype.startFromCurrentValues = function (time) { - return this.start(time, true); - }; - Tween.prototype._setupProperties = function (_object, _valuesStart, _valuesEnd, _valuesStartRepeat, overrideStartingValues) { - for (var property in _valuesEnd) { - var startValue = _object[property]; - var startValueIsArray = Array.isArray(startValue); - var propType = startValueIsArray ? 'array' : typeof startValue; - var isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property]); - // If `to()` specifies a property that doesn't exist in the source object, - // we should not set that property in the object - if (propType === 'undefined' || propType === 'function') { - continue; - } - // Check if an Array was provided as property value - if (isInterpolationList) { - var endValues = _valuesEnd[property]; - if (endValues.length === 0) { - continue; - } - // Handle an array of relative values. - // Creates a local copy of the Array with the start value at the front - var temp = [startValue]; - for (var i = 0, l = endValues.length; i < l; i += 1) { - var value = this._handleRelativeValue(startValue, endValues[i]); - if (isNaN(value)) { - isInterpolationList = false; - console.warn('Found invalid interpolation list. Skipping.'); - break; - } - temp.push(value); - } - if (isInterpolationList) { - // if (_valuesStart[property] === undefined) { // handle end values only the first time. NOT NEEDED? setupProperties is now guarded by _propertiesAreSetUp. - _valuesEnd[property] = temp; - // } - } - } - // handle the deepness of the values - if ((propType === 'object' || startValueIsArray) && startValue && !isInterpolationList) { - _valuesStart[property] = startValueIsArray ? [] : {}; - var nestedObject = startValue; - for (var prop in nestedObject) { - _valuesStart[property][prop] = nestedObject[prop]; - } - // TODO? repeat nested values? And yoyo? And array values? - _valuesStartRepeat[property] = startValueIsArray ? [] : {}; - var endValues = _valuesEnd[property]; - // If dynamic is not enabled, clone the end values instead of using the passed-in end values. - if (!this._isDynamic) { - var tmp = {}; - for (var prop in endValues) - tmp[prop] = endValues[prop]; - _valuesEnd[property] = endValues = tmp; - } - this._setupProperties(nestedObject, _valuesStart[property], endValues, _valuesStartRepeat[property], overrideStartingValues); - } - else { - // Save the starting value, but only once unless override is requested. - if (typeof _valuesStart[property] === 'undefined' || overrideStartingValues) { - _valuesStart[property] = startValue; - } - if (!startValueIsArray) { - // eslint-disable-next-line - // @ts-ignore FIXME? - _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings - } - if (isInterpolationList) { - // eslint-disable-next-line - // @ts-ignore FIXME? - _valuesStartRepeat[property] = _valuesEnd[property].slice().reverse(); - } - else { - _valuesStartRepeat[property] = _valuesStart[property] || 0; - } - } - } - }; - Tween.prototype.stop = function () { - if (!this._isChainStopped) { - this._isChainStopped = true; - this.stopChainedTweens(); - } - if (!this._isPlaying) { - return this; - } - // eslint-disable-next-line - this._group && this._group.remove(this); - this._isPlaying = false; - this._isPaused = false; - if (this._onStopCallback) { - this._onStopCallback(this._object); - } - return this; - }; - Tween.prototype.end = function () { - this._goToEnd = true; - this.update(Infinity); - return this; - }; - Tween.prototype.pause = function (time) { - if (time === void 0) { time = now(); } - if (this._isPaused || !this._isPlaying) { - return this; - } - this._isPaused = true; - this._pauseStart = time; - // eslint-disable-next-line - this._group && this._group.remove(this); - return this; - }; - Tween.prototype.resume = function (time) { - if (time === void 0) { time = now(); } - if (!this._isPaused || !this._isPlaying) { - return this; - } - this._isPaused = false; - this._startTime += time - this._pauseStart; - this._pauseStart = 0; - // eslint-disable-next-line - this._group && this._group.add(this); - return this; - }; - Tween.prototype.stopChainedTweens = function () { - for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) { - this._chainedTweens[i].stop(); - } - return this; - }; - Tween.prototype.group = function (group) { - if (group === void 0) { group = mainGroup; } - this._group = group; - return this; - }; - Tween.prototype.delay = function (amount) { - if (amount === void 0) { amount = 0; } - this._delayTime = amount; - return this; - }; - Tween.prototype.repeat = function (times) { - if (times === void 0) { times = 0; } - this._initialRepeat = times; - this._repeat = times; - return this; - }; - Tween.prototype.repeatDelay = function (amount) { - this._repeatDelayTime = amount; - return this; - }; - Tween.prototype.yoyo = function (yoyo) { - if (yoyo === void 0) { yoyo = false; } - this._yoyo = yoyo; - return this; - }; - Tween.prototype.easing = function (easingFunction) { - if (easingFunction === void 0) { easingFunction = Easing.Linear.None; } - this._easingFunction = easingFunction; - return this; - }; - Tween.prototype.interpolation = function (interpolationFunction) { - if (interpolationFunction === void 0) { interpolationFunction = Interpolation.Linear; } - this._interpolationFunction = interpolationFunction; - return this; - }; - // eslint-disable-next-line - Tween.prototype.chain = function () { - var tweens = []; - for (var _i = 0; _i < arguments.length; _i++) { - tweens[_i] = arguments[_i]; - } - this._chainedTweens = tweens; - return this; - }; - Tween.prototype.onStart = function (callback) { - this._onStartCallback = callback; - return this; - }; - Tween.prototype.onEveryStart = function (callback) { - this._onEveryStartCallback = callback; - return this; - }; - Tween.prototype.onUpdate = function (callback) { - this._onUpdateCallback = callback; - return this; - }; - Tween.prototype.onRepeat = function (callback) { - this._onRepeatCallback = callback; - return this; - }; - Tween.prototype.onComplete = function (callback) { - this._onCompleteCallback = callback; - return this; - }; - Tween.prototype.onStop = function (callback) { - this._onStopCallback = callback; - return this; - }; - /** - * @returns true if the tween is still playing after the update, false - * otherwise (calling update on a paused tween still returns true because - * it is still playing, just paused). - */ - Tween.prototype.update = function (time, autoStart) { - if (time === void 0) { time = now(); } - if (autoStart === void 0) { autoStart = true; } - if (this._isPaused) - return true; - var property; - var elapsed; - var endTime = this._startTime + this._duration; - if (!this._goToEnd && !this._isPlaying) { - if (time > endTime) - return false; - if (autoStart) - this.start(time, true); - } - this._goToEnd = false; - if (time < this._startTime) { - return true; - } - if (this._onStartCallbackFired === false) { - if (this._onStartCallback) { - this._onStartCallback(this._object); - } - this._onStartCallbackFired = true; - } - if (this._onEveryStartCallbackFired === false) { - if (this._onEveryStartCallback) { - this._onEveryStartCallback(this._object); - } - this._onEveryStartCallbackFired = true; - } - elapsed = (time - this._startTime) / this._duration; - elapsed = this._duration === 0 || elapsed > 1 ? 1 : elapsed; - var value = this._easingFunction(elapsed); - // properties transformations - this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value); - if (this._onUpdateCallback) { - this._onUpdateCallback(this._object, elapsed); - } - if (elapsed === 1) { - if (this._repeat > 0) { - if (isFinite(this._repeat)) { - this._repeat--; - } - // Reassign starting values, restart by making startTime = now - for (property in this._valuesStartRepeat) { - if (!this._yoyo && typeof this._valuesEnd[property] === 'string') { - this._valuesStartRepeat[property] = - // eslint-disable-next-line - // @ts-ignore FIXME? - this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]); - } - if (this._yoyo) { - this._swapEndStartRepeatValues(property); - } - this._valuesStart[property] = this._valuesStartRepeat[property]; - } - if (this._yoyo) { - this._reversed = !this._reversed; - } - if (this._repeatDelayTime !== undefined) { - this._startTime = time + this._repeatDelayTime; - } - else { - this._startTime = time + this._delayTime; - } - if (this._onRepeatCallback) { - this._onRepeatCallback(this._object); - } - this._onEveryStartCallbackFired = false; - return true; - } - else { - if (this._onCompleteCallback) { - this._onCompleteCallback(this._object); - } - for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) { - // Make the chained tweens start exactly at the time they should, - // even if the `update()` method was called way past the duration of the tween - this._chainedTweens[i].start(this._startTime + this._duration, false); - } - this._isPlaying = false; - return false; - } - } - return true; - }; - Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) { - for (var property in _valuesEnd) { - // Don't update properties that do not exist in the source object - if (_valuesStart[property] === undefined) { - continue; - } - var start = _valuesStart[property] || 0; - var end = _valuesEnd[property]; - var startIsArray = Array.isArray(_object[property]); - var endIsArray = Array.isArray(end); - var isInterpolationList = !startIsArray && endIsArray; - if (isInterpolationList) { - _object[property] = this._interpolationFunction(end, value); - } - else if (typeof end === 'object' && end) { - // eslint-disable-next-line - // @ts-ignore FIXME? - this._updateProperties(_object[property], start, end, value); - } - else { - // Parses relative end values with start as base (e.g.: +10, -3) - end = this._handleRelativeValue(start, end); - // Protect against non numeric properties. - if (typeof end === 'number') { - // eslint-disable-next-line - // @ts-ignore FIXME? - _object[property] = start + (end - start) * value; - } - } - } - }; - Tween.prototype._handleRelativeValue = function (start, end) { - if (typeof end !== 'string') { - return end; - } - if (end.charAt(0) === '+' || end.charAt(0) === '-') { - return start + parseFloat(end); - } - return parseFloat(end); - }; - Tween.prototype._swapEndStartRepeatValues = function (property) { - var tmp = this._valuesStartRepeat[property]; - var endValue = this._valuesEnd[property]; - if (typeof endValue === 'string') { - this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue); - } - else { - this._valuesStartRepeat[property] = this._valuesEnd[property]; - } - this._valuesEnd[property] = tmp; - }; - return Tween; - }()); - /** - * Controlling groups of tweens - * - * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components. - * In these cases, you may want to create your own smaller groups of tweens. - */ - var TWEEN = mainGroup; - // This is the best way to export things in a way that's compatible with both ES - // Modules and CommonJS, without build hacks, and so as not to break the - // existing API. - // https://github.com/rollup/rollup/issues/1961#issuecomment-423037881 - TWEEN.getAll.bind(TWEEN); - TWEEN.removeAll.bind(TWEEN); - TWEEN.add.bind(TWEEN); - TWEEN.remove.bind(TWEEN); - var update = TWEEN.update.bind(TWEEN); - - function _iterableToArrayLimit$1(arr, i) { - var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; - if (null != _i) { - var _s, - _e, - _x, - _r, - _arr = [], - _n = !0, - _d = !1; - try { - if (_x = (_i = _i.call(arr)).next, 0 === i) { - if (Object(_i) !== _i) return; - _n = !1; - } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); - } catch (err) { - _d = !0, _e = err; - } finally { - try { - if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; - } finally { - if (_d) throw _e; - } - } - return _arr; - } - } - function _classCallCheck$1(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - function _defineProperties$1(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, _toPropertyKey$2(descriptor.key), descriptor); - } - } - function _createClass$1(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties$1(Constructor.prototype, protoProps); - if (staticProps) _defineProperties$1(Constructor, staticProps); - Object.defineProperty(Constructor, "prototype", { - writable: false - }); - return Constructor; - } - function _slicedToArray$1(arr, i) { - return _arrayWithHoles$1(arr) || _iterableToArrayLimit$1(arr, i) || _unsupportedIterableToArray$2(arr, i) || _nonIterableRest$1(); - } - function _arrayWithHoles$1(arr) { - if (Array.isArray(arr)) return arr; - } - function _unsupportedIterableToArray$2(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray$2(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$2(o, minLen); - } - function _arrayLikeToArray$2(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; - } - function _nonIterableRest$1() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _toPrimitive$2(input, hint) { - if (typeof input !== "object" || input === null) return input; - var prim = input[Symbol.toPrimitive]; - if (prim !== undefined) { - var res = prim.call(input, hint || "default"); - if (typeof res !== "object") return res; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return (hint === "string" ? String : Number)(input); - } - function _toPropertyKey$2(arg) { - var key = _toPrimitive$2(arg, "string"); - return typeof key === "symbol" ? key : String(key); - } - - var Prop = /*#__PURE__*/_createClass$1(function Prop(name, _ref) { - var _ref$default = _ref["default"], - defaultVal = _ref$default === void 0 ? null : _ref$default, - _ref$triggerUpdate = _ref.triggerUpdate, - triggerUpdate = _ref$triggerUpdate === void 0 ? true : _ref$triggerUpdate, - _ref$onChange = _ref.onChange, - onChange = _ref$onChange === void 0 ? function (newVal, state) {} : _ref$onChange; - _classCallCheck$1(this, Prop); - this.name = name; - this.defaultVal = defaultVal; - this.triggerUpdate = triggerUpdate; - this.onChange = onChange; - }); - function index$3 (_ref2) { - var _ref2$stateInit = _ref2.stateInit, - stateInit = _ref2$stateInit === void 0 ? function () { - return {}; - } : _ref2$stateInit, - _ref2$props = _ref2.props, - rawProps = _ref2$props === void 0 ? {} : _ref2$props, - _ref2$methods = _ref2.methods, - methods = _ref2$methods === void 0 ? {} : _ref2$methods, - _ref2$aliases = _ref2.aliases, - aliases = _ref2$aliases === void 0 ? {} : _ref2$aliases, - _ref2$init = _ref2.init, - initFn = _ref2$init === void 0 ? function () {} : _ref2$init, - _ref2$update = _ref2.update, - updateFn = _ref2$update === void 0 ? function () {} : _ref2$update; - // Parse props into Prop instances - var props = Object.keys(rawProps).map(function (propName) { - return new Prop(propName, rawProps[propName]); - }); - return function () { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - // Holds component state - var state = Object.assign({}, stateInit instanceof Function ? stateInit(options) : stateInit, - // Support plain objects for backwards compatibility - { - initialised: false - }); - - // keeps track of which props triggered an update - var changedProps = {}; - - // Component constructor - function comp(nodeElement) { - initStatic(nodeElement, options); - digest(); - return comp; - } - var initStatic = function initStatic(nodeElement, options) { - initFn.call(comp, nodeElement, state, options); - state.initialised = true; - }; - var digest = debounce(function () { - if (!state.initialised) { - return; - } - updateFn.call(comp, state, changedProps); - changedProps = {}; - }, 1); - - // Getter/setter methods - props.forEach(function (prop) { - comp[prop.name] = getSetProp(prop); - function getSetProp(_ref3) { - var prop = _ref3.name, - _ref3$triggerUpdate = _ref3.triggerUpdate, - redigest = _ref3$triggerUpdate === void 0 ? false : _ref3$triggerUpdate, - _ref3$onChange = _ref3.onChange, - onChange = _ref3$onChange === void 0 ? function (newVal, state) {} : _ref3$onChange, - _ref3$defaultVal = _ref3.defaultVal, - defaultVal = _ref3$defaultVal === void 0 ? null : _ref3$defaultVal; - return function (_) { - var curVal = state[prop]; - if (!arguments.length) { - return curVal; - } // Getter mode - - var val = _ === undefined ? defaultVal : _; // pick default if value passed is undefined - state[prop] = val; - onChange.call(comp, val, state, curVal); - - // track changed props - !changedProps.hasOwnProperty(prop) && (changedProps[prop] = curVal); - if (redigest) { - digest(); - } - return comp; - }; - } - }); - - // Other methods - Object.keys(methods).forEach(function (methodName) { - comp[methodName] = function () { - var _methods$methodName; - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - return (_methods$methodName = methods[methodName]).call.apply(_methods$methodName, [comp, state].concat(args)); - }; - }); - - // Link aliases - Object.entries(aliases).forEach(function (_ref4) { - var _ref5 = _slicedToArray$1(_ref4, 2), - alias = _ref5[0], - target = _ref5[1]; - return comp[alias] = comp[target]; - }); - - // Reset all component props to their default value - comp.resetProps = function () { - props.forEach(function (prop) { - comp[prop.name](prop.defaultVal); - }); - return comp; - }; - - // - - comp.resetProps(); // Apply all prop defaults - state._rerender = digest; // Expose digest method - - return comp; - }; - } - - var index$2 = (function (p) { - return typeof p === 'function' ? p // fn - : typeof p === 'string' ? function (obj) { - return obj[p]; - } // property name - : function (obj) { - return p; - }; - }); // constant - - // This file is autogenerated. It's used to publish ESM to npm. - function _typeof(obj) { - "@babel/helpers - typeof"; - - return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }, _typeof(obj); - } - - // https://github.com/bgrins/TinyColor - // Brian Grinstead, MIT License - - var trimLeft = /^\s+/; - var trimRight = /\s+$/; - function tinycolor(color, opts) { - color = color ? color : ""; - opts = opts || {}; - - // If input is already a tinycolor, return itself - if (color instanceof tinycolor) { - return color; - } - // If we are called as a function, call using new instead - if (!(this instanceof tinycolor)) { - return new tinycolor(color, opts); - } - var rgb = inputToRGB(color); - this._originalInput = color, this._r = rgb.r, this._g = rgb.g, this._b = rgb.b, this._a = rgb.a, this._roundA = Math.round(100 * this._a) / 100, this._format = opts.format || rgb.format; - this._gradientType = opts.gradientType; - - // Don't let the range of [0,255] come back in [0,1]. - // Potentially lose a little bit of precision here, but will fix issues where - // .5 gets interpreted as half of the total, instead of half of 1 - // If it was supposed to be 128, this was already taken care of by `inputToRgb` - if (this._r < 1) this._r = Math.round(this._r); - if (this._g < 1) this._g = Math.round(this._g); - if (this._b < 1) this._b = Math.round(this._b); - this._ok = rgb.ok; - } - tinycolor.prototype = { - isDark: function isDark() { - return this.getBrightness() < 128; - }, - isLight: function isLight() { - return !this.isDark(); - }, - isValid: function isValid() { - return this._ok; - }, - getOriginalInput: function getOriginalInput() { - return this._originalInput; - }, - getFormat: function getFormat() { - return this._format; - }, - getAlpha: function getAlpha() { - return this._a; - }, - getBrightness: function getBrightness() { - //http://www.w3.org/TR/AERT#color-contrast - var rgb = this.toRgb(); - return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; - }, - getLuminance: function getLuminance() { - //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef - var rgb = this.toRgb(); - var RsRGB, GsRGB, BsRGB, R, G, B; - RsRGB = rgb.r / 255; - GsRGB = rgb.g / 255; - BsRGB = rgb.b / 255; - if (RsRGB <= 0.03928) R = RsRGB / 12.92;else R = Math.pow((RsRGB + 0.055) / 1.055, 2.4); - if (GsRGB <= 0.03928) G = GsRGB / 12.92;else G = Math.pow((GsRGB + 0.055) / 1.055, 2.4); - if (BsRGB <= 0.03928) B = BsRGB / 12.92;else B = Math.pow((BsRGB + 0.055) / 1.055, 2.4); - return 0.2126 * R + 0.7152 * G + 0.0722 * B; - }, - setAlpha: function setAlpha(value) { - this._a = boundAlpha(value); - this._roundA = Math.round(100 * this._a) / 100; - return this; - }, - toHsv: function toHsv() { - var hsv = rgbToHsv(this._r, this._g, this._b); - return { - h: hsv.h * 360, - s: hsv.s, - v: hsv.v, - a: this._a - }; - }, - toHsvString: function toHsvString() { - var hsv = rgbToHsv(this._r, this._g, this._b); - var h = Math.round(hsv.h * 360), - s = Math.round(hsv.s * 100), - v = Math.round(hsv.v * 100); - return this._a == 1 ? "hsv(" + h + ", " + s + "%, " + v + "%)" : "hsva(" + h + ", " + s + "%, " + v + "%, " + this._roundA + ")"; - }, - toHsl: function toHsl() { - var hsl = rgbToHsl(this._r, this._g, this._b); - return { - h: hsl.h * 360, - s: hsl.s, - l: hsl.l, - a: this._a - }; - }, - toHslString: function toHslString() { - var hsl = rgbToHsl(this._r, this._g, this._b); - var h = Math.round(hsl.h * 360), - s = Math.round(hsl.s * 100), - l = Math.round(hsl.l * 100); - return this._a == 1 ? "hsl(" + h + ", " + s + "%, " + l + "%)" : "hsla(" + h + ", " + s + "%, " + l + "%, " + this._roundA + ")"; - }, - toHex: function toHex(allow3Char) { - return rgbToHex(this._r, this._g, this._b, allow3Char); - }, - toHexString: function toHexString(allow3Char) { - return "#" + this.toHex(allow3Char); - }, - toHex8: function toHex8(allow4Char) { - return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char); - }, - toHex8String: function toHex8String(allow4Char) { - return "#" + this.toHex8(allow4Char); - }, - toRgb: function toRgb() { - return { - r: Math.round(this._r), - g: Math.round(this._g), - b: Math.round(this._b), - a: this._a - }; - }, - toRgbString: function toRgbString() { - return this._a == 1 ? "rgb(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ")" : "rgba(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ", " + this._roundA + ")"; - }, - toPercentageRgb: function toPercentageRgb() { - return { - r: Math.round(bound01(this._r, 255) * 100) + "%", - g: Math.round(bound01(this._g, 255) * 100) + "%", - b: Math.round(bound01(this._b, 255) * 100) + "%", - a: this._a - }; - }, - toPercentageRgbString: function toPercentageRgbString() { - return this._a == 1 ? "rgb(" + Math.round(bound01(this._r, 255) * 100) + "%, " + Math.round(bound01(this._g, 255) * 100) + "%, " + Math.round(bound01(this._b, 255) * 100) + "%)" : "rgba(" + Math.round(bound01(this._r, 255) * 100) + "%, " + Math.round(bound01(this._g, 255) * 100) + "%, " + Math.round(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; - }, - toName: function toName() { - if (this._a === 0) { - return "transparent"; - } - if (this._a < 1) { - return false; - } - return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; - }, - toFilter: function toFilter(secondColor) { - var hex8String = "#" + rgbaToArgbHex(this._r, this._g, this._b, this._a); - var secondHex8String = hex8String; - var gradientType = this._gradientType ? "GradientType = 1, " : ""; - if (secondColor) { - var s = tinycolor(secondColor); - secondHex8String = "#" + rgbaToArgbHex(s._r, s._g, s._b, s._a); - } - return "progid:DXImageTransform.Microsoft.gradient(" + gradientType + "startColorstr=" + hex8String + ",endColorstr=" + secondHex8String + ")"; - }, - toString: function toString(format) { - var formatSet = !!format; - format = format || this._format; - var formattedString = false; - var hasAlpha = this._a < 1 && this._a >= 0; - var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); - if (needsAlphaFormat) { - // Special case for "transparent", all other non-alpha formats - // will return rgba when there is transparency. - if (format === "name" && this._a === 0) { - return this.toName(); - } - return this.toRgbString(); - } - if (format === "rgb") { - formattedString = this.toRgbString(); - } - if (format === "prgb") { - formattedString = this.toPercentageRgbString(); - } - if (format === "hex" || format === "hex6") { - formattedString = this.toHexString(); - } - if (format === "hex3") { - formattedString = this.toHexString(true); - } - if (format === "hex4") { - formattedString = this.toHex8String(true); - } - if (format === "hex8") { - formattedString = this.toHex8String(); - } - if (format === "name") { - formattedString = this.toName(); - } - if (format === "hsl") { - formattedString = this.toHslString(); - } - if (format === "hsv") { - formattedString = this.toHsvString(); - } - return formattedString || this.toHexString(); - }, - clone: function clone() { - return tinycolor(this.toString()); - }, - _applyModification: function _applyModification(fn, args) { - var color = fn.apply(null, [this].concat([].slice.call(args))); - this._r = color._r; - this._g = color._g; - this._b = color._b; - this.setAlpha(color._a); - return this; - }, - lighten: function lighten() { - return this._applyModification(_lighten, arguments); - }, - brighten: function brighten() { - return this._applyModification(_brighten, arguments); - }, - darken: function darken() { - return this._applyModification(_darken, arguments); - }, - desaturate: function desaturate() { - return this._applyModification(_desaturate, arguments); - }, - saturate: function saturate() { - return this._applyModification(_saturate, arguments); - }, - greyscale: function greyscale() { - return this._applyModification(_greyscale, arguments); - }, - spin: function spin() { - return this._applyModification(_spin, arguments); - }, - _applyCombination: function _applyCombination(fn, args) { - return fn.apply(null, [this].concat([].slice.call(args))); - }, - analogous: function analogous() { - return this._applyCombination(_analogous, arguments); - }, - complement: function complement() { - return this._applyCombination(_complement, arguments); - }, - monochromatic: function monochromatic() { - return this._applyCombination(_monochromatic, arguments); - }, - splitcomplement: function splitcomplement() { - return this._applyCombination(_splitcomplement, arguments); - }, - // Disabled until https://github.com/bgrins/TinyColor/issues/254 - // polyad: function (number) { - // return this._applyCombination(polyad, [number]); - // }, - triad: function triad() { - return this._applyCombination(polyad, [3]); - }, - tetrad: function tetrad() { - return this._applyCombination(polyad, [4]); - } - }; - - // If input is an object, force 1 into "1.0" to handle ratios properly - // String input requires "1.0" as input, so 1 will be treated as 1 - tinycolor.fromRatio = function (color, opts) { - if (_typeof(color) == "object") { - var newColor = {}; - for (var i in color) { - if (color.hasOwnProperty(i)) { - if (i === "a") { - newColor[i] = color[i]; - } else { - newColor[i] = convertToPercentage(color[i]); - } - } - } - color = newColor; - } - return tinycolor(color, opts); - }; - - // Given a string or object, convert that input to RGB - // Possible string inputs: - // - // "red" - // "#f00" or "f00" - // "#ff0000" or "ff0000" - // "#ff000000" or "ff000000" - // "rgb 255 0 0" or "rgb (255, 0, 0)" - // "rgb 1.0 0 0" or "rgb (1, 0, 0)" - // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" - // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" - // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" - // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" - // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" - // - function inputToRGB(color) { - var rgb = { - r: 0, - g: 0, - b: 0 - }; - var a = 1; - var s = null; - var v = null; - var l = null; - var ok = false; - var format = false; - if (typeof color == "string") { - color = stringInputToObject(color); - } - if (_typeof(color) == "object") { - if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { - rgb = rgbToRgb(color.r, color.g, color.b); - ok = true; - format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; - } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { - s = convertToPercentage(color.s); - v = convertToPercentage(color.v); - rgb = hsvToRgb(color.h, s, v); - ok = true; - format = "hsv"; - } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { - s = convertToPercentage(color.s); - l = convertToPercentage(color.l); - rgb = hslToRgb(color.h, s, l); - ok = true; - format = "hsl"; - } - if (color.hasOwnProperty("a")) { - a = color.a; - } - } - a = boundAlpha(a); - return { - ok: ok, - format: color.format || format, - r: Math.min(255, Math.max(rgb.r, 0)), - g: Math.min(255, Math.max(rgb.g, 0)), - b: Math.min(255, Math.max(rgb.b, 0)), - a: a - }; - } - - // Conversion Functions - // -------------------- - - // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: - // - - // `rgbToRgb` - // Handle bounds / percentage checking to conform to CSS color spec - // - // *Assumes:* r, g, b in [0, 255] or [0, 1] - // *Returns:* { r, g, b } in [0, 255] - function rgbToRgb(r, g, b) { - return { - r: bound01(r, 255) * 255, - g: bound01(g, 255) * 255, - b: bound01(b, 255) * 255 - }; - } - - // `rgbToHsl` - // Converts an RGB color value to HSL. - // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] - // *Returns:* { h, s, l } in [0,1] - function rgbToHsl(r, g, b) { - r = bound01(r, 255); - g = bound01(g, 255); - b = bound01(b, 255); - var max = Math.max(r, g, b), - min = Math.min(r, g, b); - var h, - s, - l = (max + min) / 2; - if (max == min) { - h = s = 0; // achromatic - } else { - var d = max - min; - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch (max) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / d + 2; - break; - case b: - h = (r - g) / d + 4; - break; - } - h /= 6; - } - return { - h: h, - s: s, - l: l - }; - } - - // `hslToRgb` - // Converts an HSL color value to RGB. - // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] - // *Returns:* { r, g, b } in the set [0, 255] - function hslToRgb(h, s, l) { - var r, g, b; - h = bound01(h, 360); - s = bound01(s, 100); - l = bound01(l, 100); - function hue2rgb(p, q, t) { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - } - if (s === 0) { - r = g = b = l; // achromatic - } else { - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - return { - r: r * 255, - g: g * 255, - b: b * 255 - }; - } - - // `rgbToHsv` - // Converts an RGB color value to HSV - // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] - // *Returns:* { h, s, v } in [0,1] - function rgbToHsv(r, g, b) { - r = bound01(r, 255); - g = bound01(g, 255); - b = bound01(b, 255); - var max = Math.max(r, g, b), - min = Math.min(r, g, b); - var h, - s, - v = max; - var d = max - min; - s = max === 0 ? 0 : d / max; - if (max == min) { - h = 0; // achromatic - } else { - switch (max) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / d + 2; - break; - case b: - h = (r - g) / d + 4; - break; - } - h /= 6; - } - return { - h: h, - s: s, - v: v - }; - } - - // `hsvToRgb` - // Converts an HSV color value to RGB. - // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] - // *Returns:* { r, g, b } in the set [0, 255] - function hsvToRgb(h, s, v) { - h = bound01(h, 360) * 6; - s = bound01(s, 100); - v = bound01(v, 100); - var i = Math.floor(h), - f = h - i, - p = v * (1 - s), - q = v * (1 - f * s), - t = v * (1 - (1 - f) * s), - mod = i % 6, - r = [v, q, p, p, t, v][mod], - g = [t, v, v, q, p, p][mod], - b = [p, p, t, v, v, q][mod]; - return { - r: r * 255, - g: g * 255, - b: b * 255 - }; - } - - // `rgbToHex` - // Converts an RGB color to hex - // Assumes r, g, and b are contained in the set [0, 255] - // Returns a 3 or 6 character hex - function rgbToHex(r, g, b, allow3Char) { - var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))]; - - // Return a 3 character hex if possible - if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { - return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); - } - return hex.join(""); - } - - // `rgbaToHex` - // Converts an RGBA color plus alpha transparency to hex - // Assumes r, g, b are contained in the set [0, 255] and - // a in [0, 1]. Returns a 4 or 8 character rgba hex - function rgbaToHex(r, g, b, a, allow4Char) { - var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16)), pad2(convertDecimalToHex(a))]; - - // Return a 4 character hex if possible - if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { - return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); - } - return hex.join(""); - } - - // `rgbaToArgbHex` - // Converts an RGBA color to an ARGB Hex8 string - // Rarely used, but required for "toFilter()" - function rgbaToArgbHex(r, g, b, a) { - var hex = [pad2(convertDecimalToHex(a)), pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))]; - return hex.join(""); - } - - // `equals` - // Can be called with any tinycolor input - tinycolor.equals = function (color1, color2) { - if (!color1 || !color2) return false; - return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); - }; - tinycolor.random = function () { - return tinycolor.fromRatio({ - r: Math.random(), - g: Math.random(), - b: Math.random() - }); - }; - - // Modification Functions - // ---------------------- - // Thanks to less.js for some of the basics here - // - - function _desaturate(color, amount) { - amount = amount === 0 ? 0 : amount || 10; - var hsl = tinycolor(color).toHsl(); - hsl.s -= amount / 100; - hsl.s = clamp01(hsl.s); - return tinycolor(hsl); - } - function _saturate(color, amount) { - amount = amount === 0 ? 0 : amount || 10; - var hsl = tinycolor(color).toHsl(); - hsl.s += amount / 100; - hsl.s = clamp01(hsl.s); - return tinycolor(hsl); - } - function _greyscale(color) { - return tinycolor(color).desaturate(100); - } - function _lighten(color, amount) { - amount = amount === 0 ? 0 : amount || 10; - var hsl = tinycolor(color).toHsl(); - hsl.l += amount / 100; - hsl.l = clamp01(hsl.l); - return tinycolor(hsl); - } - function _brighten(color, amount) { - amount = amount === 0 ? 0 : amount || 10; - var rgb = tinycolor(color).toRgb(); - rgb.r = Math.max(0, Math.min(255, rgb.r - Math.round(255 * -(amount / 100)))); - rgb.g = Math.max(0, Math.min(255, rgb.g - Math.round(255 * -(amount / 100)))); - rgb.b = Math.max(0, Math.min(255, rgb.b - Math.round(255 * -(amount / 100)))); - return tinycolor(rgb); - } - function _darken(color, amount) { - amount = amount === 0 ? 0 : amount || 10; - var hsl = tinycolor(color).toHsl(); - hsl.l -= amount / 100; - hsl.l = clamp01(hsl.l); - return tinycolor(hsl); - } - - // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. - // Values outside of this range will be wrapped into this range. - function _spin(color, amount) { - var hsl = tinycolor(color).toHsl(); - var hue = (hsl.h + amount) % 360; - hsl.h = hue < 0 ? 360 + hue : hue; - return tinycolor(hsl); - } - - // Combination Functions - // --------------------- - // Thanks to jQuery xColor for some of the ideas behind these - // - - function _complement(color) { - var hsl = tinycolor(color).toHsl(); - hsl.h = (hsl.h + 180) % 360; - return tinycolor(hsl); - } - function polyad(color, number) { - if (isNaN(number) || number <= 0) { - throw new Error("Argument to polyad must be a positive number"); - } - var hsl = tinycolor(color).toHsl(); - var result = [tinycolor(color)]; - var step = 360 / number; - for (var i = 1; i < number; i++) { - result.push(tinycolor({ - h: (hsl.h + i * step) % 360, - s: hsl.s, - l: hsl.l - })); - } - return result; - } - function _splitcomplement(color) { - var hsl = tinycolor(color).toHsl(); - var h = hsl.h; - return [tinycolor(color), tinycolor({ - h: (h + 72) % 360, - s: hsl.s, - l: hsl.l - }), tinycolor({ - h: (h + 216) % 360, - s: hsl.s, - l: hsl.l - })]; - } - function _analogous(color, results, slices) { - results = results || 6; - slices = slices || 30; - var hsl = tinycolor(color).toHsl(); - var part = 360 / slices; - var ret = [tinycolor(color)]; - for (hsl.h = (hsl.h - (part * results >> 1) + 720) % 360; --results;) { - hsl.h = (hsl.h + part) % 360; - ret.push(tinycolor(hsl)); - } - return ret; - } - function _monochromatic(color, results) { - results = results || 6; - var hsv = tinycolor(color).toHsv(); - var h = hsv.h, - s = hsv.s, - v = hsv.v; - var ret = []; - var modification = 1 / results; - while (results--) { - ret.push(tinycolor({ - h: h, - s: s, - v: v - })); - v = (v + modification) % 1; - } - return ret; - } - - // Utility Functions - // --------------------- - - tinycolor.mix = function (color1, color2, amount) { - amount = amount === 0 ? 0 : amount || 50; - var rgb1 = tinycolor(color1).toRgb(); - var rgb2 = tinycolor(color2).toRgb(); - var p = amount / 100; - var rgba = { - r: (rgb2.r - rgb1.r) * p + rgb1.r, - g: (rgb2.g - rgb1.g) * p + rgb1.g, - b: (rgb2.b - rgb1.b) * p + rgb1.b, - a: (rgb2.a - rgb1.a) * p + rgb1.a - }; - return tinycolor(rgba); - }; - - // Readability Functions - // --------------------- - // false - // tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false - tinycolor.isReadable = function (color1, color2, wcag2) { - var readability = tinycolor.readability(color1, color2); - var wcag2Parms, out; - out = false; - wcag2Parms = validateWCAG2Parms(wcag2); - switch (wcag2Parms.level + wcag2Parms.size) { - case "AAsmall": - case "AAAlarge": - out = readability >= 4.5; - break; - case "AAlarge": - out = readability >= 3; - break; - case "AAAsmall": - out = readability >= 7; - break; - } - return out; - }; - - // `mostReadable` - // Given a base color and a list of possible foreground or background - // colors for that base, returns the most readable color. - // Optionally returns Black or White if the most readable color is unreadable. - // *Example* - // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" - // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" - // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" - // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" - tinycolor.mostReadable = function (baseColor, colorList, args) { - var bestColor = null; - var bestScore = 0; - var readability; - var includeFallbackColors, level, size; - args = args || {}; - includeFallbackColors = args.includeFallbackColors; - level = args.level; - size = args.size; - for (var i = 0; i < colorList.length; i++) { - readability = tinycolor.readability(baseColor, colorList[i]); - if (readability > bestScore) { - bestScore = readability; - bestColor = tinycolor(colorList[i]); - } - } - if (tinycolor.isReadable(baseColor, bestColor, { - level: level, - size: size - }) || !includeFallbackColors) { - return bestColor; - } else { - args.includeFallbackColors = false; - return tinycolor.mostReadable(baseColor, ["#fff", "#000"], args); - } - }; - - // Big List of Colors - // ------------------ - // - var names = tinycolor.names = { - aliceblue: "f0f8ff", - antiquewhite: "faebd7", - aqua: "0ff", - aquamarine: "7fffd4", - azure: "f0ffff", - beige: "f5f5dc", - bisque: "ffe4c4", - black: "000", - blanchedalmond: "ffebcd", - blue: "00f", - blueviolet: "8a2be2", - brown: "a52a2a", - burlywood: "deb887", - burntsienna: "ea7e5d", - cadetblue: "5f9ea0", - chartreuse: "7fff00", - chocolate: "d2691e", - coral: "ff7f50", - cornflowerblue: "6495ed", - cornsilk: "fff8dc", - crimson: "dc143c", - cyan: "0ff", - darkblue: "00008b", - darkcyan: "008b8b", - darkgoldenrod: "b8860b", - darkgray: "a9a9a9", - darkgreen: "006400", - darkgrey: "a9a9a9", - darkkhaki: "bdb76b", - darkmagenta: "8b008b", - darkolivegreen: "556b2f", - darkorange: "ff8c00", - darkorchid: "9932cc", - darkred: "8b0000", - darksalmon: "e9967a", - darkseagreen: "8fbc8f", - darkslateblue: "483d8b", - darkslategray: "2f4f4f", - darkslategrey: "2f4f4f", - darkturquoise: "00ced1", - darkviolet: "9400d3", - deeppink: "ff1493", - deepskyblue: "00bfff", - dimgray: "696969", - dimgrey: "696969", - dodgerblue: "1e90ff", - firebrick: "b22222", - floralwhite: "fffaf0", - forestgreen: "228b22", - fuchsia: "f0f", - gainsboro: "dcdcdc", - ghostwhite: "f8f8ff", - gold: "ffd700", - goldenrod: "daa520", - gray: "808080", - green: "008000", - greenyellow: "adff2f", - grey: "808080", - honeydew: "f0fff0", - hotpink: "ff69b4", - indianred: "cd5c5c", - indigo: "4b0082", - ivory: "fffff0", - khaki: "f0e68c", - lavender: "e6e6fa", - lavenderblush: "fff0f5", - lawngreen: "7cfc00", - lemonchiffon: "fffacd", - lightblue: "add8e6", - lightcoral: "f08080", - lightcyan: "e0ffff", - lightgoldenrodyellow: "fafad2", - lightgray: "d3d3d3", - lightgreen: "90ee90", - lightgrey: "d3d3d3", - lightpink: "ffb6c1", - lightsalmon: "ffa07a", - lightseagreen: "20b2aa", - lightskyblue: "87cefa", - lightslategray: "789", - lightslategrey: "789", - lightsteelblue: "b0c4de", - lightyellow: "ffffe0", - lime: "0f0", - limegreen: "32cd32", - linen: "faf0e6", - magenta: "f0f", - maroon: "800000", - mediumaquamarine: "66cdaa", - mediumblue: "0000cd", - mediumorchid: "ba55d3", - mediumpurple: "9370db", - mediumseagreen: "3cb371", - mediumslateblue: "7b68ee", - mediumspringgreen: "00fa9a", - mediumturquoise: "48d1cc", - mediumvioletred: "c71585", - midnightblue: "191970", - mintcream: "f5fffa", - mistyrose: "ffe4e1", - moccasin: "ffe4b5", - navajowhite: "ffdead", - navy: "000080", - oldlace: "fdf5e6", - olive: "808000", - olivedrab: "6b8e23", - orange: "ffa500", - orangered: "ff4500", - orchid: "da70d6", - palegoldenrod: "eee8aa", - palegreen: "98fb98", - paleturquoise: "afeeee", - palevioletred: "db7093", - papayawhip: "ffefd5", - peachpuff: "ffdab9", - peru: "cd853f", - pink: "ffc0cb", - plum: "dda0dd", - powderblue: "b0e0e6", - purple: "800080", - rebeccapurple: "663399", - red: "f00", - rosybrown: "bc8f8f", - royalblue: "4169e1", - saddlebrown: "8b4513", - salmon: "fa8072", - sandybrown: "f4a460", - seagreen: "2e8b57", - seashell: "fff5ee", - sienna: "a0522d", - silver: "c0c0c0", - skyblue: "87ceeb", - slateblue: "6a5acd", - slategray: "708090", - slategrey: "708090", - snow: "fffafa", - springgreen: "00ff7f", - steelblue: "4682b4", - tan: "d2b48c", - teal: "008080", - thistle: "d8bfd8", - tomato: "ff6347", - turquoise: "40e0d0", - violet: "ee82ee", - wheat: "f5deb3", - white: "fff", - whitesmoke: "f5f5f5", - yellow: "ff0", - yellowgreen: "9acd32" - }; - - // Make it easy to access colors via `hexNames[hex]` - var hexNames = tinycolor.hexNames = flip(names); - - // Utilities - // --------- - - // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` - function flip(o) { - var flipped = {}; - for (var i in o) { - if (o.hasOwnProperty(i)) { - flipped[o[i]] = i; - } - } - return flipped; - } - - // Return a valid alpha value [0,1] with all invalid values being set to 1 - function boundAlpha(a) { - a = parseFloat(a); - if (isNaN(a) || a < 0 || a > 1) { - a = 1; - } - return a; - } - - // Take input from [0, n] and return it as [0, 1] - function bound01(n, max) { - if (isOnePointZero(n)) n = "100%"; - var processPercent = isPercentage(n); - n = Math.min(max, Math.max(0, parseFloat(n))); - - // Automatically convert percentage into number - if (processPercent) { - n = parseInt(n * max, 10) / 100; - } - - // Handle floating point rounding errors - if (Math.abs(n - max) < 0.000001) { - return 1; - } - - // Convert into [0, 1] range if it isn't already - return n % max / parseFloat(max); - } - - // Force a number between 0 and 1 - function clamp01(val) { - return Math.min(1, Math.max(0, val)); - } - - // Parse a base-16 hex value into a base-10 integer - function parseIntFromHex(val) { - return parseInt(val, 16); - } - - // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 - // - function isOnePointZero(n) { - return typeof n == "string" && n.indexOf(".") != -1 && parseFloat(n) === 1; - } - - // Check to see if string passed in is a percentage - function isPercentage(n) { - return typeof n === "string" && n.indexOf("%") != -1; - } - - // Force a hex value to have 2 characters - function pad2(c) { - return c.length == 1 ? "0" + c : "" + c; - } - - // Replace a decimal with it's percentage value - function convertToPercentage(n) { - if (n <= 1) { - n = n * 100 + "%"; - } - return n; - } - - // Converts a decimal to a hex value - function convertDecimalToHex(d) { - return Math.round(parseFloat(d) * 255).toString(16); - } - // Converts a hex value to a decimal - function convertHexToDecimal(h) { - return parseIntFromHex(h) / 255; - } - var matchers = function () { - // - var CSS_INTEGER = "[-\\+]?\\d+%?"; - - // - var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; - - // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. - var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; - - // Actual matching. - // Parentheses and commas are optional, but not required. - // Whitespace can take the place of commas or opening paren - var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; - var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; - return { - CSS_UNIT: new RegExp(CSS_UNIT), - rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), - rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), - hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), - hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), - hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), - hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), - hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, - hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ - }; - }(); - - // `isValidCSSUnit` - // Take in a single string / number and check to see if it looks like a CSS unit - // (see `matchers` above for definition). - function isValidCSSUnit(color) { - return !!matchers.CSS_UNIT.exec(color); - } - - // `stringInputToObject` - // Permissive string parsing. Take in a number of formats, and output an object - // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` - function stringInputToObject(color) { - color = color.replace(trimLeft, "").replace(trimRight, "").toLowerCase(); - var named = false; - if (names[color]) { - color = names[color]; - named = true; - } else if (color == "transparent") { - return { - r: 0, - g: 0, - b: 0, - a: 0, - format: "name" - }; - } - - // Try to match string input using regular expressions. - // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] - // Just return an object and let the conversion functions handle that. - // This way the result will be the same whether the tinycolor is initialized with string or object. - var match; - if (match = matchers.rgb.exec(color)) { - return { - r: match[1], - g: match[2], - b: match[3] - }; - } - if (match = matchers.rgba.exec(color)) { - return { - r: match[1], - g: match[2], - b: match[3], - a: match[4] - }; - } - if (match = matchers.hsl.exec(color)) { - return { - h: match[1], - s: match[2], - l: match[3] - }; - } - if (match = matchers.hsla.exec(color)) { - return { - h: match[1], - s: match[2], - l: match[3], - a: match[4] - }; - } - if (match = matchers.hsv.exec(color)) { - return { - h: match[1], - s: match[2], - v: match[3] - }; - } - if (match = matchers.hsva.exec(color)) { - return { - h: match[1], - s: match[2], - v: match[3], - a: match[4] - }; - } - if (match = matchers.hex8.exec(color)) { - return { - r: parseIntFromHex(match[1]), - g: parseIntFromHex(match[2]), - b: parseIntFromHex(match[3]), - a: convertHexToDecimal(match[4]), - format: named ? "name" : "hex8" - }; - } - if (match = matchers.hex6.exec(color)) { - return { - r: parseIntFromHex(match[1]), - g: parseIntFromHex(match[2]), - b: parseIntFromHex(match[3]), - format: named ? "name" : "hex" - }; - } - if (match = matchers.hex4.exec(color)) { - return { - r: parseIntFromHex(match[1] + "" + match[1]), - g: parseIntFromHex(match[2] + "" + match[2]), - b: parseIntFromHex(match[3] + "" + match[3]), - a: convertHexToDecimal(match[4] + "" + match[4]), - format: named ? "name" : "hex8" - }; - } - if (match = matchers.hex3.exec(color)) { - return { - r: parseIntFromHex(match[1] + "" + match[1]), - g: parseIntFromHex(match[2] + "" + match[2]), - b: parseIntFromHex(match[3] + "" + match[3]), - format: named ? "name" : "hex" - }; - } - return false; - } - function validateWCAG2Parms(parms) { - // return valid WCAG2 parms for isReadable. - // If input parms are invalid, return {"level":"AA", "size":"small"} - var level, size; - parms = parms || { - level: "AA", - size: "small" - }; - level = (parms.level || "AA").toUpperCase(); - size = (parms.size || "small").toLowerCase(); - if (level !== "AA" && level !== "AAA") { - level = "AA"; - } - if (size !== "small" && size !== "large") { - size = "small"; - } - return { - level: level, - size: size - }; - } - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, _toPropertyKey$1(descriptor.key), descriptor); - } - } - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - Object.defineProperty(Constructor, "prototype", { - writable: false - }); - return Constructor; - } - function _toConsumableArray$1(arr) { - return _arrayWithoutHoles$1(arr) || _iterableToArray$1(arr) || _unsupportedIterableToArray$1(arr) || _nonIterableSpread$1(); - } - function _arrayWithoutHoles$1(arr) { - if (Array.isArray(arr)) return _arrayLikeToArray$1(arr); - } - function _iterableToArray$1(iter) { - if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); - } - function _unsupportedIterableToArray$1(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); - } - function _arrayLikeToArray$1(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; - } - function _nonIterableSpread$1() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _toPrimitive$1(input, hint) { - if (typeof input !== "object" || input === null) return input; - var prim = input[Symbol.toPrimitive]; - if (prim !== undefined) { - var res = prim.call(input, hint || "default"); - if (typeof res !== "object") return res; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return (hint === "string" ? String : Number)(input); - } - function _toPropertyKey$1(arg) { - var key = _toPrimitive$1(arg, "string"); - return typeof key === "symbol" ? key : String(key); - } - - var ENTROPY = 123; // Raise numbers to prevent collisions in lower indexes - - var int2HexColor = function int2HexColor(num) { - return "#".concat(Math.min(num, Math.pow(2, 24)).toString(16).padStart(6, '0')); - }; - var rgb2Int = function rgb2Int(r, g, b) { - return (r << 16) + (g << 8) + b; - }; - var colorStr2Int = function colorStr2Int(str) { - var _tinyColor$toRgb = tinycolor(str).toRgb(), - r = _tinyColor$toRgb.r, - g = _tinyColor$toRgb.g, - b = _tinyColor$toRgb.b; - return rgb2Int(r, g, b); - }; - var checksum = function checksum(n, csBits) { - return n * ENTROPY % Math.pow(2, csBits); - }; - var _default = /*#__PURE__*/function () { - function _default() { - var csBits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 6; - _classCallCheck(this, _default); - this.csBits = csBits; // How many bits to reserve for checksum. Will eat away into the usable size of the registry. - this.registry = ['__reserved for background__']; // indexed objects for rgb lookup; - } - _createClass(_default, [{ - key: "register", - value: function register(obj) { - if (this.registry.length >= Math.pow(2, 24 - this.csBits)) { - // color has 24 bits (-checksum) - return null; // Registry is full - } - - var idx = this.registry.length; - var cs = checksum(idx, this.csBits); - var color = int2HexColor(idx + (cs << 24 - this.csBits)); - this.registry.push(obj); - return color; - } - }, { - key: "lookup", - value: function lookup(color) { - var n = typeof color === 'string' ? colorStr2Int(color) : rgb2Int.apply(void 0, _toConsumableArray$1(color)); - if (!n) return null; // 0 index is reserved for background - - var idx = n & Math.pow(2, 24 - this.csBits) - 1; // registry index - var cs = n >> 24 - this.csBits & Math.pow(2, this.csBits) - 1; // extract bits reserved for checksum - - if (checksum(idx, this.csBits) !== cs || idx >= this.registry.length) return null; // failed checksum or registry out of bounds - - return this.registry[idx]; - } - }]); - return _default; - }(); - - function d3ForceCenter(x, y, z) { - var nodes, strength = 1; - - if (x == null) x = 0; - if (y == null) y = 0; - if (z == null) z = 0; - - function force() { - var i, - n = nodes.length, - node, - sx = 0, - sy = 0, - sz = 0; - - for (i = 0; i < n; ++i) { - node = nodes[i], sx += node.x || 0, sy += node.y || 0, sz += node.z || 0; - } - - for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, sz = (sz / n - z) * strength, i = 0; i < n; ++i) { - node = nodes[i]; - if (sx) { node.x -= sx; } - if (sy) { node.y -= sy; } - if (sz) { node.z -= sz; } - } - } - - force.initialize = function(_) { - nodes = _; - }; - - force.x = function(_) { - return arguments.length ? (x = +_, force) : x; - }; - - force.y = function(_) { - return arguments.length ? (y = +_, force) : y; - }; - - force.z = function(_) { - return arguments.length ? (z = +_, force) : z; - }; - - force.strength = function(_) { - return arguments.length ? (strength = +_, force) : strength; - }; - - return force; - } - - function tree_add$2(d) { - const x = +this._x.call(null, d); - return add$2(this.cover(x), x, d); - } - - function add$2(tree, x, d) { - if (isNaN(x)) return tree; // ignore invalid points - - var parent, - node = tree._root, - leaf = {data: d}, - x0 = tree._x0, - x1 = tree._x1, - xm, - xp, - right, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return tree._root = leaf, tree; - - // Find the existing leaf for the new point, or add it. - while (node.length) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (parent = node, !(node = node[i = +right])) return parent[i] = leaf, tree; - } - - // Is the new point is exactly coincident with the existing point? - xp = +tree._x.call(null, node.data); - if (x === xp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; - - // Otherwise, split the leaf node until the old and new point are separated. - do { - parent = parent ? parent[i] = new Array(2) : tree._root = new Array(2); - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - } while ((i = +right) === (j = +(xp >= xm))); - return parent[j] = node, parent[i] = leaf, tree; - } - - function addAll$2(data) { - if (!Array.isArray(data)) data = Array.from(data); - const n = data.length; - const xz = new Float64Array(n); - let x0 = Infinity, - x1 = -Infinity; - - // Compute the points and their extent. - for (let i = 0, x; i < n; ++i) { - if (isNaN(x = +this._x.call(null, data[i]))) continue; - xz[i] = x; - if (x < x0) x0 = x; - if (x > x1) x1 = x; - } - - // If there were no (valid) points, abort. - if (x0 > x1) return this; - - // Expand the tree to cover the new points. - this.cover(x0).cover(x1); - - // Add the new points. - for (let i = 0; i < n; ++i) { - add$2(this, xz[i], data[i]); - } - - return this; - } - - function tree_cover$2(x) { - if (isNaN(x = +x)) return this; // ignore invalid points - - var x0 = this._x0, - x1 = this._x1; - - // If the binarytree has no extent, initialize them. - // Integer extent are necessary so that if we later double the extent, - // the existing half boundaries don’t change due to floating point error! - if (isNaN(x0)) { - x1 = (x0 = Math.floor(x)) + 1; - } - - // Otherwise, double repeatedly to cover. - else { - var z = x1 - x0 || 1, - node = this._root, - parent, - i; - - while (x0 > x || x >= x1) { - i = +(x < x0); - parent = new Array(2), parent[i] = node, node = parent, z *= 2; - switch (i) { - case 0: x1 = x0 + z; break; - case 1: x0 = x1 - z; break; - } - } - - if (this._root && this._root.length) this._root = node; - } - - this._x0 = x0; - this._x1 = x1; - return this; - } - - function tree_data$2() { - var data = []; - this.visit(function(node) { - if (!node.length) do data.push(node.data); while (node = node.next) - }); - return data; - } - - function tree_extent$2(_) { - return arguments.length - ? this.cover(+_[0][0]).cover(+_[1][0]) - : isNaN(this._x0) ? undefined : [[this._x0], [this._x1]]; - } - - function Half(node, x0, x1) { - this.node = node; - this.x0 = x0; - this.x1 = x1; - } - - function tree_find$2(x, radius) { - var data, - x0 = this._x0, - x1, - x2, - x3 = this._x1, - halves = [], - node = this._root, - q, - i; - - if (node) halves.push(new Half(node, x0, x3)); - if (radius == null) radius = Infinity; - else { - x0 = x - radius; - x3 = x + radius; - } - - while (q = halves.pop()) { - - // Stop searching if this half can’t contain a closer node. - if (!(node = q.node) - || (x1 = q.x0) > x3 - || (x2 = q.x1) < x0) continue; - - // Bisect the current half. - if (node.length) { - var xm = (x1 + x2) / 2; - - halves.push( - new Half(node[1], xm, x2), - new Half(node[0], x1, xm) - ); - - // Visit the closest half first. - if (i = +(x >= xm)) { - q = halves[halves.length - 1]; - halves[halves.length - 1] = halves[halves.length - 1 - i]; - halves[halves.length - 1 - i] = q; - } - } - - // Visit this point. (Visiting coincident points isn’t necessary!) - else { - var d = Math.abs(x - +this._x.call(null, node.data)); - if (d < radius) { - radius = d; - x0 = x - d; - x3 = x + d; - data = node.data; - } - } - } - - return data; - } - - function tree_remove$2(d) { - if (isNaN(x = +this._x.call(null, d))) return this; // ignore invalid points - - var parent, - node = this._root, - retainer, - previous, - next, - x0 = this._x0, - x1 = this._x1, - x, - xm, - right, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return this; - - // Find the leaf node for the point. - // While descending, also retain the deepest parent with a non-removed sibling. - if (node.length) while (true) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (!(parent = node, node = node[i = +right])) return this; - if (!node.length) break; - if (parent[(i + 1) & 1]) retainer = parent, j = i; - } - - // Find the point to remove. - while (node.data !== d) if (!(previous = node, node = node.next)) return this; - if (next = node.next) delete node.next; - - // If there are multiple coincident points, remove just the point. - if (previous) return (next ? previous.next = next : delete previous.next), this; - - // If this is the root point, remove it. - if (!parent) return this._root = next, this; - - // Remove this leaf. - next ? parent[i] = next : delete parent[i]; - - // If the parent now contains exactly one leaf, collapse superfluous parents. - if ((node = parent[0] || parent[1]) - && node === (parent[1] || parent[0]) - && !node.length) { - if (retainer) retainer[j] = node; - else this._root = node; - } - - return this; - } - - function removeAll$2(data) { - for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); - return this; - } - - function tree_root$2() { - return this._root; - } - - function tree_size$2() { - var size = 0; - this.visit(function(node) { - if (!node.length) do ++size; while (node = node.next) - }); - return size; - } - - function tree_visit$2(callback) { - var halves = [], q, node = this._root, child, x0, x1; - if (node) halves.push(new Half(node, this._x0, this._x1)); - while (q = halves.pop()) { - if (!callback(node = q.node, x0 = q.x0, x1 = q.x1) && node.length) { - var xm = (x0 + x1) / 2; - if (child = node[1]) halves.push(new Half(child, xm, x1)); - if (child = node[0]) halves.push(new Half(child, x0, xm)); - } - } - return this; - } - - function tree_visitAfter$2(callback) { - var halves = [], next = [], q; - if (this._root) halves.push(new Half(this._root, this._x0, this._x1)); - while (q = halves.pop()) { - var node = q.node; - if (node.length) { - var child, x0 = q.x0, x1 = q.x1, xm = (x0 + x1) / 2; - if (child = node[0]) halves.push(new Half(child, x0, xm)); - if (child = node[1]) halves.push(new Half(child, xm, x1)); - } - next.push(q); - } - while (q = next.pop()) { - callback(q.node, q.x0, q.x1); - } - return this; - } - - function defaultX$2(d) { - return d[0]; - } - - function tree_x$2(_) { - return arguments.length ? (this._x = _, this) : this._x; - } - - function binarytree(nodes, x) { - var tree = new Binarytree(x == null ? defaultX$2 : x, NaN, NaN); - return nodes == null ? tree : tree.addAll(nodes); - } - - function Binarytree(x, x0, x1) { - this._x = x; - this._x0 = x0; - this._x1 = x1; - this._root = undefined; - } - - function leaf_copy$2(leaf) { - var copy = {data: leaf.data}, next = copy; - while (leaf = leaf.next) next = next.next = {data: leaf.data}; - return copy; - } - - var treeProto$2 = binarytree.prototype = Binarytree.prototype; - - treeProto$2.copy = function() { - var copy = new Binarytree(this._x, this._x0, this._x1), - node = this._root, - nodes, - child; - - if (!node) return copy; - - if (!node.length) return copy._root = leaf_copy$2(node), copy; - - nodes = [{source: node, target: copy._root = new Array(2)}]; - while (node = nodes.pop()) { - for (var i = 0; i < 2; ++i) { - if (child = node.source[i]) { - if (child.length) nodes.push({source: child, target: node.target[i] = new Array(2)}); - else node.target[i] = leaf_copy$2(child); - } - } - } - - return copy; - }; - - treeProto$2.add = tree_add$2; - treeProto$2.addAll = addAll$2; - treeProto$2.cover = tree_cover$2; - treeProto$2.data = tree_data$2; - treeProto$2.extent = tree_extent$2; - treeProto$2.find = tree_find$2; - treeProto$2.remove = tree_remove$2; - treeProto$2.removeAll = removeAll$2; - treeProto$2.root = tree_root$2; - treeProto$2.size = tree_size$2; - treeProto$2.visit = tree_visit$2; - treeProto$2.visitAfter = tree_visitAfter$2; - treeProto$2.x = tree_x$2; - - function tree_add$1(d) { - const x = +this._x.call(null, d), - y = +this._y.call(null, d); - return add$1(this.cover(x, y), x, y, d); - } - - function add$1(tree, x, y, d) { - if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points - - var parent, - node = tree._root, - leaf = {data: d}, - x0 = tree._x0, - y0 = tree._y0, - x1 = tree._x1, - y1 = tree._y1, - xm, - ym, - xp, - yp, - right, - bottom, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return tree._root = leaf, tree; - - // Find the existing leaf for the new point, or add it. - while (node.length) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; - } - - // Is the new point is exactly coincident with the existing point? - xp = +tree._x.call(null, node.data); - yp = +tree._y.call(null, node.data); - if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; - - // Otherwise, split the leaf node until the old and new point are separated. - do { - parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); - return parent[j] = node, parent[i] = leaf, tree; - } - - function addAll$1(data) { - var d, i, n = data.length, - x, - y, - xz = new Array(n), - yz = new Array(n), - x0 = Infinity, - y0 = Infinity, - x1 = -Infinity, - y1 = -Infinity; - - // Compute the points and their extent. - for (i = 0; i < n; ++i) { - if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; - xz[i] = x; - yz[i] = y; - if (x < x0) x0 = x; - if (x > x1) x1 = x; - if (y < y0) y0 = y; - if (y > y1) y1 = y; - } - - // If there were no (valid) points, abort. - if (x0 > x1 || y0 > y1) return this; - - // Expand the tree to cover the new points. - this.cover(x0, y0).cover(x1, y1); - - // Add the new points. - for (i = 0; i < n; ++i) { - add$1(this, xz[i], yz[i], data[i]); - } - - return this; - } - - function tree_cover$1(x, y) { - if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points - - var x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1; - - // If the quadtree has no extent, initialize them. - // Integer extent are necessary so that if we later double the extent, - // the existing quadrant boundaries don’t change due to floating point error! - if (isNaN(x0)) { - x1 = (x0 = Math.floor(x)) + 1; - y1 = (y0 = Math.floor(y)) + 1; - } - - // Otherwise, double repeatedly to cover. - else { - var z = x1 - x0 || 1, - node = this._root, - parent, - i; - - while (x0 > x || x >= x1 || y0 > y || y >= y1) { - i = (y < y0) << 1 | (x < x0); - parent = new Array(4), parent[i] = node, node = parent, z *= 2; - switch (i) { - case 0: x1 = x0 + z, y1 = y0 + z; break; - case 1: x0 = x1 - z, y1 = y0 + z; break; - case 2: x1 = x0 + z, y0 = y1 - z; break; - case 3: x0 = x1 - z, y0 = y1 - z; break; - } - } - - if (this._root && this._root.length) this._root = node; - } - - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - return this; - } - - function tree_data$1() { - var data = []; - this.visit(function(node) { - if (!node.length) do data.push(node.data); while (node = node.next) - }); - return data; - } - - function tree_extent$1(_) { - return arguments.length - ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) - : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; - } - - function Quad(node, x0, y0, x1, y1) { - this.node = node; - this.x0 = x0; - this.y0 = y0; - this.x1 = x1; - this.y1 = y1; - } - - function tree_find$1(x, y, radius) { - var data, - x0 = this._x0, - y0 = this._y0, - x1, - y1, - x2, - y2, - x3 = this._x1, - y3 = this._y1, - quads = [], - node = this._root, - q, - i; - - if (node) quads.push(new Quad(node, x0, y0, x3, y3)); - if (radius == null) radius = Infinity; - else { - x0 = x - radius, y0 = y - radius; - x3 = x + radius, y3 = y + radius; - radius *= radius; - } - - while (q = quads.pop()) { - - // Stop searching if this quadrant can’t contain a closer node. - if (!(node = q.node) - || (x1 = q.x0) > x3 - || (y1 = q.y0) > y3 - || (x2 = q.x1) < x0 - || (y2 = q.y1) < y0) continue; - - // Bisect the current quadrant. - if (node.length) { - var xm = (x1 + x2) / 2, - ym = (y1 + y2) / 2; - - quads.push( - new Quad(node[3], xm, ym, x2, y2), - new Quad(node[2], x1, ym, xm, y2), - new Quad(node[1], xm, y1, x2, ym), - new Quad(node[0], x1, y1, xm, ym) - ); - - // Visit the closest quadrant first. - if (i = (y >= ym) << 1 | (x >= xm)) { - q = quads[quads.length - 1]; - quads[quads.length - 1] = quads[quads.length - 1 - i]; - quads[quads.length - 1 - i] = q; - } - } - - // Visit this point. (Visiting coincident points isn’t necessary!) - else { - var dx = x - +this._x.call(null, node.data), - dy = y - +this._y.call(null, node.data), - d2 = dx * dx + dy * dy; - if (d2 < radius) { - var d = Math.sqrt(radius = d2); - x0 = x - d, y0 = y - d; - x3 = x + d, y3 = y + d; - data = node.data; - } - } - } - - return data; - } - - function tree_remove$1(d) { - if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points - - var parent, - node = this._root, - retainer, - previous, - next, - x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1, - x, - y, - xm, - ym, - right, - bottom, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return this; - - // Find the leaf node for the point. - // While descending, also retain the deepest parent with a non-removed sibling. - if (node.length) while (true) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (!(parent = node, node = node[i = bottom << 1 | right])) return this; - if (!node.length) break; - if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; - } - - // Find the point to remove. - while (node.data !== d) if (!(previous = node, node = node.next)) return this; - if (next = node.next) delete node.next; - - // If there are multiple coincident points, remove just the point. - if (previous) return (next ? previous.next = next : delete previous.next), this; - - // If this is the root point, remove it. - if (!parent) return this._root = next, this; - - // Remove this leaf. - next ? parent[i] = next : delete parent[i]; - - // If the parent now contains exactly one leaf, collapse superfluous parents. - if ((node = parent[0] || parent[1] || parent[2] || parent[3]) - && node === (parent[3] || parent[2] || parent[1] || parent[0]) - && !node.length) { - if (retainer) retainer[j] = node; - else this._root = node; - } - - return this; - } - - function removeAll$1(data) { - for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); - return this; - } - - function tree_root$1() { - return this._root; - } - - function tree_size$1() { - var size = 0; - this.visit(function(node) { - if (!node.length) do ++size; while (node = node.next) - }); - return size; - } - - function tree_visit$1(callback) { - var quads = [], q, node = this._root, child, x0, y0, x1, y1; - if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { - var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - } - } - return this; - } - - function tree_visitAfter$1(callback) { - var quads = [], next = [], q; - if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - var node = q.node; - if (node.length) { - var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - } - next.push(q); - } - while (q = next.pop()) { - callback(q.node, q.x0, q.y0, q.x1, q.y1); - } - return this; - } - - function defaultX$1(d) { - return d[0]; - } - - function tree_x$1(_) { - return arguments.length ? (this._x = _, this) : this._x; - } - - function defaultY$1(d) { - return d[1]; - } - - function tree_y$1(_) { - return arguments.length ? (this._y = _, this) : this._y; - } - - function quadtree(nodes, x, y) { - var tree = new Quadtree(x == null ? defaultX$1 : x, y == null ? defaultY$1 : y, NaN, NaN, NaN, NaN); - return nodes == null ? tree : tree.addAll(nodes); - } - - function Quadtree(x, y, x0, y0, x1, y1) { - this._x = x; - this._y = y; - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - this._root = undefined; - } - - function leaf_copy$1(leaf) { - var copy = {data: leaf.data}, next = copy; - while (leaf = leaf.next) next = next.next = {data: leaf.data}; - return copy; - } - - var treeProto$1 = quadtree.prototype = Quadtree.prototype; - - treeProto$1.copy = function() { - var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), - node = this._root, - nodes, - child; - - if (!node) return copy; - - if (!node.length) return copy._root = leaf_copy$1(node), copy; - - nodes = [{source: node, target: copy._root = new Array(4)}]; - while (node = nodes.pop()) { - for (var i = 0; i < 4; ++i) { - if (child = node.source[i]) { - if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); - else node.target[i] = leaf_copy$1(child); - } - } - } - - return copy; - }; - - treeProto$1.add = tree_add$1; - treeProto$1.addAll = addAll$1; - treeProto$1.cover = tree_cover$1; - treeProto$1.data = tree_data$1; - treeProto$1.extent = tree_extent$1; - treeProto$1.find = tree_find$1; - treeProto$1.remove = tree_remove$1; - treeProto$1.removeAll = removeAll$1; - treeProto$1.root = tree_root$1; - treeProto$1.size = tree_size$1; - treeProto$1.visit = tree_visit$1; - treeProto$1.visitAfter = tree_visitAfter$1; - treeProto$1.x = tree_x$1; - treeProto$1.y = tree_y$1; - - function tree_add(d) { - const x = +this._x.call(null, d), - y = +this._y.call(null, d), - z = +this._z.call(null, d); - return add(this.cover(x, y, z), x, y, z, d); - } - - function add(tree, x, y, z, d) { - if (isNaN(x) || isNaN(y) || isNaN(z)) return tree; // ignore invalid points - - var parent, - node = tree._root, - leaf = {data: d}, - x0 = tree._x0, - y0 = tree._y0, - z0 = tree._z0, - x1 = tree._x1, - y1 = tree._y1, - z1 = tree._z1, - xm, - ym, - zm, - xp, - yp, - zp, - right, - bottom, - deep, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return tree._root = leaf, tree; - - // Find the existing leaf for the new point, or add it. - while (node.length) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm; - if (parent = node, !(node = node[i = deep << 2 | bottom << 1 | right])) return parent[i] = leaf, tree; - } - - // Is the new point is exactly coincident with the existing point? - xp = +tree._x.call(null, node.data); - yp = +tree._y.call(null, node.data); - zp = +tree._z.call(null, node.data); - if (x === xp && y === yp && z === zp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; - - // Otherwise, split the leaf node until the old and new point are separated. - do { - parent = parent ? parent[i] = new Array(8) : tree._root = new Array(8); - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm; - } while ((i = deep << 2 | bottom << 1 | right) === (j = (zp >= zm) << 2 | (yp >= ym) << 1 | (xp >= xm))); - return parent[j] = node, parent[i] = leaf, tree; - } - - function addAll(data) { - if (!Array.isArray(data)) data = Array.from(data); - const n = data.length; - const xz = new Float64Array(n); - const yz = new Float64Array(n); - const zz = new Float64Array(n); - let x0 = Infinity, - y0 = Infinity, - z0 = Infinity, - x1 = -Infinity, - y1 = -Infinity, - z1 = -Infinity; - - // Compute the points and their extent. - for (let i = 0, d, x, y, z; i < n; ++i) { - if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d)) || isNaN(z = +this._z.call(null, d))) continue; - xz[i] = x; - yz[i] = y; - zz[i] = z; - if (x < x0) x0 = x; - if (x > x1) x1 = x; - if (y < y0) y0 = y; - if (y > y1) y1 = y; - if (z < z0) z0 = z; - if (z > z1) z1 = z; - } - - // If there were no (valid) points, abort. - if (x0 > x1 || y0 > y1 || z0 > z1) return this; - - // Expand the tree to cover the new points. - this.cover(x0, y0, z0).cover(x1, y1, z1); - - // Add the new points. - for (let i = 0; i < n; ++i) { - add(this, xz[i], yz[i], zz[i], data[i]); - } - - return this; - } - - function tree_cover(x, y, z) { - if (isNaN(x = +x) || isNaN(y = +y) || isNaN(z = +z)) return this; // ignore invalid points - - var x0 = this._x0, - y0 = this._y0, - z0 = this._z0, - x1 = this._x1, - y1 = this._y1, - z1 = this._z1; - - // If the octree has no extent, initialize them. - // Integer extent are necessary so that if we later double the extent, - // the existing octant boundaries don’t change due to floating point error! - if (isNaN(x0)) { - x1 = (x0 = Math.floor(x)) + 1; - y1 = (y0 = Math.floor(y)) + 1; - z1 = (z0 = Math.floor(z)) + 1; - } - - // Otherwise, double repeatedly to cover. - else { - var t = x1 - x0 || 1, - node = this._root, - parent, - i; - - while (x0 > x || x >= x1 || y0 > y || y >= y1 || z0 > z || z >= z1) { - i = (z < z0) << 2 | (y < y0) << 1 | (x < x0); - parent = new Array(8), parent[i] = node, node = parent, t *= 2; - switch (i) { - case 0: x1 = x0 + t, y1 = y0 + t, z1 = z0 + t; break; - case 1: x0 = x1 - t, y1 = y0 + t, z1 = z0 + t; break; - case 2: x1 = x0 + t, y0 = y1 - t, z1 = z0 + t; break; - case 3: x0 = x1 - t, y0 = y1 - t, z1 = z0 + t; break; - case 4: x1 = x0 + t, y1 = y0 + t, z0 = z1 - t; break; - case 5: x0 = x1 - t, y1 = y0 + t, z0 = z1 - t; break; - case 6: x1 = x0 + t, y0 = y1 - t, z0 = z1 - t; break; - case 7: x0 = x1 - t, y0 = y1 - t, z0 = z1 - t; break; - } - } - - if (this._root && this._root.length) this._root = node; - } - - this._x0 = x0; - this._y0 = y0; - this._z0 = z0; - this._x1 = x1; - this._y1 = y1; - this._z1 = z1; - return this; - } - - function tree_data() { - var data = []; - this.visit(function(node) { - if (!node.length) do data.push(node.data); while (node = node.next) - }); - return data; - } - - function tree_extent(_) { - return arguments.length - ? this.cover(+_[0][0], +_[0][1], +_[0][2]).cover(+_[1][0], +_[1][1], +_[1][2]) - : isNaN(this._x0) ? undefined : [[this._x0, this._y0, this._z0], [this._x1, this._y1, this._z1]]; - } - - function Octant(node, x0, y0, z0, x1, y1, z1) { - this.node = node; - this.x0 = x0; - this.y0 = y0; - this.z0 = z0; - this.x1 = x1; - this.y1 = y1; - this.z1 = z1; - } - - function tree_find(x, y, z, radius) { - var data, - x0 = this._x0, - y0 = this._y0, - z0 = this._z0, - x1, - y1, - z1, - x2, - y2, - z2, - x3 = this._x1, - y3 = this._y1, - z3 = this._z1, - octs = [], - node = this._root, - q, - i; - - if (node) octs.push(new Octant(node, x0, y0, z0, x3, y3, z3)); - if (radius == null) radius = Infinity; - else { - x0 = x - radius, y0 = y - radius, z0 = z - radius; - x3 = x + radius, y3 = y + radius, z3 = z + radius; - radius *= radius; - } - - while (q = octs.pop()) { - - // Stop searching if this octant can’t contain a closer node. - if (!(node = q.node) - || (x1 = q.x0) > x3 - || (y1 = q.y0) > y3 - || (z1 = q.z0) > z3 - || (x2 = q.x1) < x0 - || (y2 = q.y1) < y0 - || (z2 = q.z1) < z0) continue; - - // Bisect the current octant. - if (node.length) { - var xm = (x1 + x2) / 2, - ym = (y1 + y2) / 2, - zm = (z1 + z2) / 2; - - octs.push( - new Octant(node[7], xm, ym, zm, x2, y2, z2), - new Octant(node[6], x1, ym, zm, xm, y2, z2), - new Octant(node[5], xm, y1, zm, x2, ym, z2), - new Octant(node[4], x1, y1, zm, xm, ym, z2), - new Octant(node[3], xm, ym, z1, x2, y2, zm), - new Octant(node[2], x1, ym, z1, xm, y2, zm), - new Octant(node[1], xm, y1, z1, x2, ym, zm), - new Octant(node[0], x1, y1, z1, xm, ym, zm) - ); - - // Visit the closest octant first. - if (i = (z >= zm) << 2 | (y >= ym) << 1 | (x >= xm)) { - q = octs[octs.length - 1]; - octs[octs.length - 1] = octs[octs.length - 1 - i]; - octs[octs.length - 1 - i] = q; - } - } - - // Visit this point. (Visiting coincident points isn’t necessary!) - else { - var dx = x - +this._x.call(null, node.data), - dy = y - +this._y.call(null, node.data), - dz = z - +this._z.call(null, node.data), - d2 = dx * dx + dy * dy + dz * dz; - if (d2 < radius) { - var d = Math.sqrt(radius = d2); - x0 = x - d, y0 = y - d, z0 = z - d; - x3 = x + d, y3 = y + d, z3 = z + d; - data = node.data; - } - } - } - - return data; - } - - function tree_remove(d) { - if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d)) || isNaN(z = +this._z.call(null, d))) return this; // ignore invalid points - - var parent, - node = this._root, - retainer, - previous, - next, - x0 = this._x0, - y0 = this._y0, - z0 = this._z0, - x1 = this._x1, - y1 = this._y1, - z1 = this._z1, - x, - y, - z, - xm, - ym, - zm, - right, - bottom, - deep, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return this; - - // Find the leaf node for the point. - // While descending, also retain the deepest parent with a non-removed sibling. - if (node.length) while (true) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm; - if (!(parent = node, node = node[i = deep << 2 | bottom << 1 | right])) return this; - if (!node.length) break; - if (parent[(i + 1) & 7] || parent[(i + 2) & 7] || parent[(i + 3) & 7] || parent[(i + 4) & 7] || parent[(i + 5) & 7] || parent[(i + 6) & 7] || parent[(i + 7) & 7]) retainer = parent, j = i; - } - - // Find the point to remove. - while (node.data !== d) if (!(previous = node, node = node.next)) return this; - if (next = node.next) delete node.next; - - // If there are multiple coincident points, remove just the point. - if (previous) return (next ? previous.next = next : delete previous.next), this; - - // If this is the root point, remove it. - if (!parent) return this._root = next, this; - - // Remove this leaf. - next ? parent[i] = next : delete parent[i]; - - // If the parent now contains exactly one leaf, collapse superfluous parents. - if ((node = parent[0] || parent[1] || parent[2] || parent[3] || parent[4] || parent[5] || parent[6] || parent[7]) - && node === (parent[7] || parent[6] || parent[5] || parent[4] || parent[3] || parent[2] || parent[1] || parent[0]) - && !node.length) { - if (retainer) retainer[j] = node; - else this._root = node; - } - - return this; - } - - function removeAll(data) { - for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); - return this; - } - - function tree_root() { - return this._root; - } - - function tree_size() { - var size = 0; - this.visit(function(node) { - if (!node.length) do ++size; while (node = node.next) - }); - return size; - } - - function tree_visit(callback) { - var octs = [], q, node = this._root, child, x0, y0, z0, x1, y1, z1; - if (node) octs.push(new Octant(node, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1)); - while (q = octs.pop()) { - if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, z0 = q.z0, x1 = q.x1, y1 = q.y1, z1 = q.z1) && node.length) { - var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2, zm = (z0 + z1) / 2; - if (child = node[7]) octs.push(new Octant(child, xm, ym, zm, x1, y1, z1)); - if (child = node[6]) octs.push(new Octant(child, x0, ym, zm, xm, y1, z1)); - if (child = node[5]) octs.push(new Octant(child, xm, y0, zm, x1, ym, z1)); - if (child = node[4]) octs.push(new Octant(child, x0, y0, zm, xm, ym, z1)); - if (child = node[3]) octs.push(new Octant(child, xm, ym, z0, x1, y1, zm)); - if (child = node[2]) octs.push(new Octant(child, x0, ym, z0, xm, y1, zm)); - if (child = node[1]) octs.push(new Octant(child, xm, y0, z0, x1, ym, zm)); - if (child = node[0]) octs.push(new Octant(child, x0, y0, z0, xm, ym, zm)); - } - } - return this; - } - - function tree_visitAfter(callback) { - var octs = [], next = [], q; - if (this._root) octs.push(new Octant(this._root, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1)); - while (q = octs.pop()) { - var node = q.node; - if (node.length) { - var child, x0 = q.x0, y0 = q.y0, z0 = q.z0, x1 = q.x1, y1 = q.y1, z1 = q.z1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2, zm = (z0 + z1) / 2; - if (child = node[0]) octs.push(new Octant(child, x0, y0, z0, xm, ym, zm)); - if (child = node[1]) octs.push(new Octant(child, xm, y0, z0, x1, ym, zm)); - if (child = node[2]) octs.push(new Octant(child, x0, ym, z0, xm, y1, zm)); - if (child = node[3]) octs.push(new Octant(child, xm, ym, z0, x1, y1, zm)); - if (child = node[4]) octs.push(new Octant(child, x0, y0, zm, xm, ym, z1)); - if (child = node[5]) octs.push(new Octant(child, xm, y0, zm, x1, ym, z1)); - if (child = node[6]) octs.push(new Octant(child, x0, ym, zm, xm, y1, z1)); - if (child = node[7]) octs.push(new Octant(child, xm, ym, zm, x1, y1, z1)); - } - next.push(q); - } - while (q = next.pop()) { - callback(q.node, q.x0, q.y0, q.z0, q.x1, q.y1, q.z1); - } - return this; - } - - function defaultX(d) { - return d[0]; - } - - function tree_x(_) { - return arguments.length ? (this._x = _, this) : this._x; - } - - function defaultY(d) { - return d[1]; - } - - function tree_y(_) { - return arguments.length ? (this._y = _, this) : this._y; - } - - function defaultZ(d) { - return d[2]; - } - - function tree_z(_) { - return arguments.length ? (this._z = _, this) : this._z; - } - - function octree(nodes, x, y, z) { - var tree = new Octree(x == null ? defaultX : x, y == null ? defaultY : y, z == null ? defaultZ : z, NaN, NaN, NaN, NaN, NaN, NaN); - return nodes == null ? tree : tree.addAll(nodes); - } - - function Octree(x, y, z, x0, y0, z0, x1, y1, z1) { - this._x = x; - this._y = y; - this._z = z; - this._x0 = x0; - this._y0 = y0; - this._z0 = z0; - this._x1 = x1; - this._y1 = y1; - this._z1 = z1; - this._root = undefined; - } - - function leaf_copy(leaf) { - var copy = {data: leaf.data}, next = copy; - while (leaf = leaf.next) next = next.next = {data: leaf.data}; - return copy; - } - - var treeProto = octree.prototype = Octree.prototype; - - treeProto.copy = function() { - var copy = new Octree(this._x, this._y, this._z, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1), - node = this._root, - nodes, - child; - - if (!node) return copy; - - if (!node.length) return copy._root = leaf_copy(node), copy; - - nodes = [{source: node, target: copy._root = new Array(8)}]; - while (node = nodes.pop()) { - for (var i = 0; i < 8; ++i) { - if (child = node.source[i]) { - if (child.length) nodes.push({source: child, target: node.target[i] = new Array(8)}); - else node.target[i] = leaf_copy(child); - } - } - } - - return copy; - }; - - treeProto.add = tree_add; - treeProto.addAll = addAll; - treeProto.cover = tree_cover; - treeProto.data = tree_data; - treeProto.extent = tree_extent; - treeProto.find = tree_find; - treeProto.remove = tree_remove; - treeProto.removeAll = removeAll; - treeProto.root = tree_root; - treeProto.size = tree_size; - treeProto.visit = tree_visit; - treeProto.visitAfter = tree_visitAfter; - treeProto.x = tree_x; - treeProto.y = tree_y; - treeProto.z = tree_z; - - function constant(x) { - return function() { - return x; - }; - } - - function jiggle(random) { - return (random() - 0.5) * 1e-6; - } - - function index$1(d) { - return d.index; - } - - function find(nodeById, nodeId) { - var node = nodeById.get(nodeId); - if (!node) throw new Error("node not found: " + nodeId); - return node; - } - - function d3ForceLink(links) { - var id = index$1, - strength = defaultStrength, - strengths, - distance = constant(30), - distances, - nodes, - nDim, - count, - bias, - random, - iterations = 1; - - if (links == null) links = []; - - function defaultStrength(link) { - return 1 / Math.min(count[link.source.index], count[link.target.index]); - } - - function force(alpha) { - for (var k = 0, n = links.length; k < iterations; ++k) { - for (var i = 0, link, source, target, x = 0, y = 0, z = 0, l, b; i < n; ++i) { - link = links[i], source = link.source, target = link.target; - x = target.x + target.vx - source.x - source.vx || jiggle(random); - if (nDim > 1) { y = target.y + target.vy - source.y - source.vy || jiggle(random); } - if (nDim > 2) { z = target.z + target.vz - source.z - source.vz || jiggle(random); } - l = Math.sqrt(x * x + y * y + z * z); - l = (l - distances[i]) / l * alpha * strengths[i]; - x *= l, y *= l, z *= l; - - target.vx -= x * (b = bias[i]); - if (nDim > 1) { target.vy -= y * b; } - if (nDim > 2) { target.vz -= z * b; } - - source.vx += x * (b = 1 - b); - if (nDim > 1) { source.vy += y * b; } - if (nDim > 2) { source.vz += z * b; } - } - } - } - - function initialize() { - if (!nodes) return; - - var i, - n = nodes.length, - m = links.length, - nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])), - link; - - for (i = 0, count = new Array(n); i < m; ++i) { - link = links[i], link.index = i; - if (typeof link.source !== "object") link.source = find(nodeById, link.source); - if (typeof link.target !== "object") link.target = find(nodeById, link.target); - count[link.source.index] = (count[link.source.index] || 0) + 1; - count[link.target.index] = (count[link.target.index] || 0) + 1; - } - - for (i = 0, bias = new Array(m); i < m; ++i) { - link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); - } - - strengths = new Array(m), initializeStrength(); - distances = new Array(m), initializeDistance(); - } - - function initializeStrength() { - if (!nodes) return; - - for (var i = 0, n = links.length; i < n; ++i) { - strengths[i] = +strength(links[i], i, links); - } - } - - function initializeDistance() { - if (!nodes) return; - - for (var i = 0, n = links.length; i < n; ++i) { - distances[i] = +distance(links[i], i, links); - } - } - - force.initialize = function(_nodes, ...args) { - nodes = _nodes; - random = args.find(arg => typeof arg === 'function') || Math.random; - nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2; - initialize(); - }; - - force.links = function(_) { - return arguments.length ? (links = _, initialize(), force) : links; - }; - - force.id = function(_) { - return arguments.length ? (id = _, force) : id; - }; - - force.iterations = function(_) { - return arguments.length ? (iterations = +_, force) : iterations; - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength; - }; - - force.distance = function(_) { - return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; - }; - - return force; - } - - // https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use - const a = 1664525; - const c = 1013904223; - const m = 4294967296; // 2^32 - - function lcg() { - let s = 1; - return () => (s = (a * s + c) % m) / m; - } - - var MAX_DIMENSIONS = 3; - - function x(d) { - return d.x; - } - - function y(d) { - return d.y; - } - - function z(d) { - return d.z; - } - - var initialRadius = 10, - initialAngleRoll = Math.PI * (3 - Math.sqrt(5)), // Golden ratio angle - initialAngleYaw = Math.PI * 20 / (9 + Math.sqrt(221)); // Markov irrational number - - function d3ForceSimulation(nodes, numDimensions) { - numDimensions = numDimensions || 2; - - var nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(numDimensions))), - simulation, - alpha = 1, - alphaMin = 0.001, - alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), - alphaTarget = 0, - velocityDecay = 0.6, - forces = new Map(), - stepper = timer(step), - event = dispatch("tick", "end"), - random = lcg(); - - if (nodes == null) nodes = []; - - function step() { - tick(); - event.call("tick", simulation); - if (alpha < alphaMin) { - stepper.stop(); - event.call("end", simulation); - } - } - - function tick(iterations) { - var i, n = nodes.length, node; - - if (iterations === undefined) iterations = 1; - - for (var k = 0; k < iterations; ++k) { - alpha += (alphaTarget - alpha) * alphaDecay; - - forces.forEach(function (force) { - force(alpha); - }); - - for (i = 0; i < n; ++i) { - node = nodes[i]; - if (node.fx == null) node.x += node.vx *= velocityDecay; - else node.x = node.fx, node.vx = 0; - if (nDim > 1) { - if (node.fy == null) node.y += node.vy *= velocityDecay; - else node.y = node.fy, node.vy = 0; - } - if (nDim > 2) { - if (node.fz == null) node.z += node.vz *= velocityDecay; - else node.z = node.fz, node.vz = 0; - } - } - } - - return simulation; - } - - function initializeNodes() { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.index = i; - if (node.fx != null) node.x = node.fx; - if (node.fy != null) node.y = node.fy; - if (node.fz != null) node.z = node.fz; - if (isNaN(node.x) || (nDim > 1 && isNaN(node.y)) || (nDim > 2 && isNaN(node.z))) { - var radius = initialRadius * (nDim > 2 ? Math.cbrt(0.5 + i) : (nDim > 1 ? Math.sqrt(0.5 + i) : i)), - rollAngle = i * initialAngleRoll, - yawAngle = i * initialAngleYaw; - - if (nDim === 1) { - node.x = radius; - } else if (nDim === 2) { - node.x = radius * Math.cos(rollAngle); - node.y = radius * Math.sin(rollAngle); - } else { // 3 dimensions: use spherical distribution along 2 irrational number angles - node.x = radius * Math.sin(rollAngle) * Math.cos(yawAngle); - node.y = radius * Math.cos(rollAngle); - node.z = radius * Math.sin(rollAngle) * Math.sin(yawAngle); - } - } - if (isNaN(node.vx) || (nDim > 1 && isNaN(node.vy)) || (nDim > 2 && isNaN(node.vz))) { - node.vx = 0; - if (nDim > 1) { node.vy = 0; } - if (nDim > 2) { node.vz = 0; } - } - } - } - - function initializeForce(force) { - if (force.initialize) force.initialize(nodes, random, nDim); - return force; - } - - initializeNodes(); - - return simulation = { - tick: tick, - - restart: function() { - return stepper.restart(step), simulation; - }, - - stop: function() { - return stepper.stop(), simulation; - }, - - numDimensions: function(_) { - return arguments.length - ? (nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(_))), forces.forEach(initializeForce), simulation) - : nDim; - }, - - nodes: function(_) { - return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes; - }, - - alpha: function(_) { - return arguments.length ? (alpha = +_, simulation) : alpha; - }, - - alphaMin: function(_) { - return arguments.length ? (alphaMin = +_, simulation) : alphaMin; - }, - - alphaDecay: function(_) { - return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; - }, - - alphaTarget: function(_) { - return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; - }, - - velocityDecay: function(_) { - return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; - }, - - randomSource: function(_) { - return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random; - }, - - force: function(name, _) { - return arguments.length > 1 ? ((_ == null ? forces.delete(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); - }, - - find: function() { - var args = Array.prototype.slice.call(arguments); - var x = args.shift() || 0, - y = (nDim > 1 ? args.shift() : null) || 0, - z = (nDim > 2 ? args.shift() : null) || 0, - radius = args.shift() || Infinity; - - var i = 0, - n = nodes.length, - dx, - dy, - dz, - d2, - node, - closest; - - radius *= radius; - - for (i = 0; i < n; ++i) { - node = nodes[i]; - dx = x - node.x; - dy = y - (node.y || 0); - dz = z - (node.z ||0); - d2 = dx * dx + dy * dy + dz * dz; - if (d2 < radius) closest = node, radius = d2; - } - - return closest; - }, - - on: function(name, _) { - return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); - } - }; - } - - function d3ForceManyBody() { - var nodes, - nDim, - node, - random, - alpha, - strength = constant(-30), - strengths, - distanceMin2 = 1, - distanceMax2 = Infinity, - theta2 = 0.81; - - function force(_) { - var i, - n = nodes.length, - tree = - (nDim === 1 ? binarytree(nodes, x) - :(nDim === 2 ? quadtree(nodes, x, y) - :(nDim === 3 ? octree(nodes, x, y, z) - :null - ))).visitAfter(accumulate); - - for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length, node; - strengths = new Array(n); - for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); - } - - function accumulate(treeNode) { - var strength = 0, q, c, weight = 0, x, y, z, i; - var numChildren = treeNode.length; - - // For internal nodes, accumulate forces from children. - if (numChildren) { - for (x = y = z = i = 0; i < numChildren; ++i) { - if ((q = treeNode[i]) && (c = Math.abs(q.value))) { - strength += q.value, weight += c, x += c * (q.x || 0), y += c * (q.y || 0), z += c * (q.z || 0); - } - } - strength *= Math.sqrt(4 / numChildren); // scale accumulated strength according to number of dimensions - - treeNode.x = x / weight; - if (nDim > 1) { treeNode.y = y / weight; } - if (nDim > 2) { treeNode.z = z / weight; } - } - - // For leaf nodes, accumulate forces from coincident nodes. - else { - q = treeNode; - q.x = q.data.x; - if (nDim > 1) { q.y = q.data.y; } - if (nDim > 2) { q.z = q.data.z; } - do strength += strengths[q.data.index]; - while (q = q.next); - } - - treeNode.value = strength; - } - - function apply(treeNode, x1, arg1, arg2, arg3) { - if (!treeNode.value) return true; - var x2 = [arg1, arg2, arg3][nDim-1]; - - var x = treeNode.x - node.x, - y = (nDim > 1 ? treeNode.y - node.y : 0), - z = (nDim > 2 ? treeNode.z - node.z : 0), - w = x2 - x1, - l = x * x + y * y + z * z; - - // Apply the Barnes-Hut approximation if possible. - // Limit forces for very close nodes; randomize direction if coincident. - if (w * w / theta2 < l) { - if (l < distanceMax2) { - if (x === 0) x = jiggle(random), l += x * x; - if (nDim > 1 && y === 0) y = jiggle(random), l += y * y; - if (nDim > 2 && z === 0) z = jiggle(random), l += z * z; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); - node.vx += x * treeNode.value * alpha / l; - if (nDim > 1) { node.vy += y * treeNode.value * alpha / l; } - if (nDim > 2) { node.vz += z * treeNode.value * alpha / l; } - } - return true; - } - - // Otherwise, process points directly. - else if (treeNode.length || l >= distanceMax2) return; - - // Limit forces for very close nodes; randomize direction if coincident. - if (treeNode.data !== node || treeNode.next) { - if (x === 0) x = jiggle(random), l += x * x; - if (nDim > 1 && y === 0) y = jiggle(random), l += y * y; - if (nDim > 2 && z === 0) z = jiggle(random), l += z * z; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); - } - - do if (treeNode.data !== node) { - w = strengths[treeNode.data.index] * alpha / l; - node.vx += x * w; - if (nDim > 1) { node.vy += y * w; } - if (nDim > 2) { node.vz += z * w; } - } while (treeNode = treeNode.next); - } - - force.initialize = function(_nodes, ...args) { - nodes = _nodes; - random = args.find(arg => typeof arg === 'function') || Math.random; - nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; - }; - - force.distanceMin = function(_) { - return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); - }; - - force.distanceMax = function(_) { - return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); - }; - - force.theta = function(_) { - return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); - }; - - return force; - } - - function d3ForceRadial(radius, x, y, z) { - var nodes, - nDim, - strength = constant(0.1), - strengths, - radiuses; - - if (typeof radius !== "function") radius = constant(+radius); - if (x == null) x = 0; - if (y == null) y = 0; - if (z == null) z = 0; - - function force(alpha) { - for (var i = 0, n = nodes.length; i < n; ++i) { - var node = nodes[i], - dx = node.x - x || 1e-6, - dy = (node.y || 0) - y || 1e-6, - dz = (node.z || 0) - z || 1e-6, - r = Math.sqrt(dx * dx + dy * dy + dz * dz), - k = (radiuses[i] - r) * strengths[i] * alpha / r; - node.vx += dx * k; - if (nDim>1) { node.vy += dy * k; } - if (nDim>2) { node.vz += dz * k; } - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - radiuses = new Array(n); - for (i = 0; i < n; ++i) { - radiuses[i] = +radius(nodes[i], i, nodes); - strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); - } - } - - force.initialize = function(initNodes, ...args) { - nodes = initNodes; - nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; - }; - - force.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; - }; - - force.x = function(_) { - return arguments.length ? (x = +_, force) : x; - }; - - force.y = function(_) { - return arguments.length ? (y = +_, force) : y; - }; - - force.z = function(_) { - return arguments.length ? (z = +_, force) : z; - }; - - return force; - } - - // math-inlining. - const { abs: abs$1, cos: cos$1, sin: sin$1, acos: acos$1, atan2, sqrt: sqrt$1, pow } = Math; - - // cube root function yielding real roots - function crt(v) { - return v < 0 ? -pow(-v, 1 / 3) : pow(v, 1 / 3); - } - - // trig constants - const pi$1 = Math.PI, - tau = 2 * pi$1, - quart = pi$1 / 2, - // float precision significant decimal - epsilon = 0.000001, - // extremas used in bbox calculation and similar algorithms - nMax = Number.MAX_SAFE_INTEGER || 9007199254740991, - nMin = Number.MIN_SAFE_INTEGER || -9007199254740991, - // a zero coordinate, which is surprisingly useful - ZERO = { x: 0, y: 0, z: 0 }; - - // Bezier utility functions - const utils = { - // Legendre-Gauss abscissae with n=24 (x_i values, defined at i=n as the roots of the nth order Legendre polynomial Pn(x)) - Tvalues: [ - -0.0640568928626056260850430826247450385909, - 0.0640568928626056260850430826247450385909, - -0.1911188674736163091586398207570696318404, - 0.1911188674736163091586398207570696318404, - -0.3150426796961633743867932913198102407864, - 0.3150426796961633743867932913198102407864, - -0.4337935076260451384870842319133497124524, - 0.4337935076260451384870842319133497124524, - -0.5454214713888395356583756172183723700107, - 0.5454214713888395356583756172183723700107, - -0.6480936519369755692524957869107476266696, - 0.6480936519369755692524957869107476266696, - -0.7401241915785543642438281030999784255232, - 0.7401241915785543642438281030999784255232, - -0.8200019859739029219539498726697452080761, - 0.8200019859739029219539498726697452080761, - -0.8864155270044010342131543419821967550873, - 0.8864155270044010342131543419821967550873, - -0.9382745520027327585236490017087214496548, - 0.9382745520027327585236490017087214496548, - -0.9747285559713094981983919930081690617411, - 0.9747285559713094981983919930081690617411, - -0.9951872199970213601799974097007368118745, - 0.9951872199970213601799974097007368118745, - ], - - // Legendre-Gauss weights with n=24 (w_i values, defined by a function linked to in the Bezier primer article) - Cvalues: [ - 0.1279381953467521569740561652246953718517, - 0.1279381953467521569740561652246953718517, - 0.1258374563468282961213753825111836887264, - 0.1258374563468282961213753825111836887264, - 0.121670472927803391204463153476262425607, - 0.121670472927803391204463153476262425607, - 0.1155056680537256013533444839067835598622, - 0.1155056680537256013533444839067835598622, - 0.1074442701159656347825773424466062227946, - 0.1074442701159656347825773424466062227946, - 0.0976186521041138882698806644642471544279, - 0.0976186521041138882698806644642471544279, - 0.086190161531953275917185202983742667185, - 0.086190161531953275917185202983742667185, - 0.0733464814110803057340336152531165181193, - 0.0733464814110803057340336152531165181193, - 0.0592985849154367807463677585001085845412, - 0.0592985849154367807463677585001085845412, - 0.0442774388174198061686027482113382288593, - 0.0442774388174198061686027482113382288593, - 0.0285313886289336631813078159518782864491, - 0.0285313886289336631813078159518782864491, - 0.0123412297999871995468056670700372915759, - 0.0123412297999871995468056670700372915759, - ], - - arcfn: function (t, derivativeFn) { - const d = derivativeFn(t); - let l = d.x * d.x + d.y * d.y; - if (typeof d.z !== "undefined") { - l += d.z * d.z; - } - return sqrt$1(l); - }, - - compute: function (t, points, _3d) { - // shortcuts - if (t === 0) { - points[0].t = 0; - return points[0]; - } - - const order = points.length - 1; - - if (t === 1) { - points[order].t = 1; - return points[order]; - } - - const mt = 1 - t; - let p = points; - - // constant? - if (order === 0) { - points[0].t = t; - return points[0]; - } - - // linear? - if (order === 1) { - const ret = { - x: mt * p[0].x + t * p[1].x, - y: mt * p[0].y + t * p[1].y, - t: t, - }; - if (_3d) { - ret.z = mt * p[0].z + t * p[1].z; - } - return ret; - } - - // quadratic/cubic curve? - if (order < 4) { - let mt2 = mt * mt, - t2 = t * t, - a, - b, - c, - d = 0; - if (order === 2) { - p = [p[0], p[1], p[2], ZERO]; - a = mt2; - b = mt * t * 2; - c = t2; - } else if (order === 3) { - a = mt2 * mt; - b = mt2 * t * 3; - c = mt * t2 * 3; - d = t * t2; - } - const ret = { - x: a * p[0].x + b * p[1].x + c * p[2].x + d * p[3].x, - y: a * p[0].y + b * p[1].y + c * p[2].y + d * p[3].y, - t: t, - }; - if (_3d) { - ret.z = a * p[0].z + b * p[1].z + c * p[2].z + d * p[3].z; - } - return ret; - } - - // higher order curves: use de Casteljau's computation - const dCpts = JSON.parse(JSON.stringify(points)); - while (dCpts.length > 1) { - for (let i = 0; i < dCpts.length - 1; i++) { - dCpts[i] = { - x: dCpts[i].x + (dCpts[i + 1].x - dCpts[i].x) * t, - y: dCpts[i].y + (dCpts[i + 1].y - dCpts[i].y) * t, - }; - if (typeof dCpts[i].z !== "undefined") { - dCpts[i].z = dCpts[i].z + (dCpts[i + 1].z - dCpts[i].z) * t; - } - } - dCpts.splice(dCpts.length - 1, 1); - } - dCpts[0].t = t; - return dCpts[0]; - }, - - computeWithRatios: function (t, points, ratios, _3d) { - const mt = 1 - t, - r = ratios, - p = points; - - let f1 = r[0], - f2 = r[1], - f3 = r[2], - f4 = r[3], - d; - - // spec for linear - f1 *= mt; - f2 *= t; - - if (p.length === 2) { - d = f1 + f2; - return { - x: (f1 * p[0].x + f2 * p[1].x) / d, - y: (f1 * p[0].y + f2 * p[1].y) / d, - z: !_3d ? false : (f1 * p[0].z + f2 * p[1].z) / d, - t: t, - }; - } - - // upgrade to quadratic - f1 *= mt; - f2 *= 2 * mt; - f3 *= t * t; - - if (p.length === 3) { - d = f1 + f2 + f3; - return { - x: (f1 * p[0].x + f2 * p[1].x + f3 * p[2].x) / d, - y: (f1 * p[0].y + f2 * p[1].y + f3 * p[2].y) / d, - z: !_3d ? false : (f1 * p[0].z + f2 * p[1].z + f3 * p[2].z) / d, - t: t, - }; - } - - // upgrade to cubic - f1 *= mt; - f2 *= 1.5 * mt; - f3 *= 3 * mt; - f4 *= t * t * t; - - if (p.length === 4) { - d = f1 + f2 + f3 + f4; - return { - x: (f1 * p[0].x + f2 * p[1].x + f3 * p[2].x + f4 * p[3].x) / d, - y: (f1 * p[0].y + f2 * p[1].y + f3 * p[2].y + f4 * p[3].y) / d, - z: !_3d - ? false - : (f1 * p[0].z + f2 * p[1].z + f3 * p[2].z + f4 * p[3].z) / d, - t: t, - }; - } - }, - - derive: function (points, _3d) { - const dpoints = []; - for (let p = points, d = p.length, c = d - 1; d > 1; d--, c--) { - const list = []; - for (let j = 0, dpt; j < c; j++) { - dpt = { - x: c * (p[j + 1].x - p[j].x), - y: c * (p[j + 1].y - p[j].y), - }; - if (_3d) { - dpt.z = c * (p[j + 1].z - p[j].z); - } - list.push(dpt); - } - dpoints.push(list); - p = list; - } - return dpoints; - }, - - between: function (v, m, M) { - return ( - (m <= v && v <= M) || - utils.approximately(v, m) || - utils.approximately(v, M) - ); - }, - - approximately: function (a, b, precision) { - return abs$1(a - b) <= (precision || epsilon); - }, - - length: function (derivativeFn) { - const z = 0.5, - len = utils.Tvalues.length; - - let sum = 0; - - for (let i = 0, t; i < len; i++) { - t = z * utils.Tvalues[i] + z; - sum += utils.Cvalues[i] * utils.arcfn(t, derivativeFn); - } - return z * sum; - }, - - map: function (v, ds, de, ts, te) { - const d1 = de - ds, - d2 = te - ts, - v2 = v - ds, - r = v2 / d1; - return ts + d2 * r; - }, - - lerp: function (r, v1, v2) { - const ret = { - x: v1.x + r * (v2.x - v1.x), - y: v1.y + r * (v2.y - v1.y), - }; - if (v1.z !== undefined && v2.z !== undefined) { - ret.z = v1.z + r * (v2.z - v1.z); - } - return ret; - }, - - pointToString: function (p) { - let s = p.x + "/" + p.y; - if (typeof p.z !== "undefined") { - s += "/" + p.z; - } - return s; - }, - - pointsToString: function (points) { - return "[" + points.map(utils.pointToString).join(", ") + "]"; - }, - - copy: function (obj) { - return JSON.parse(JSON.stringify(obj)); - }, - - angle: function (o, v1, v2) { - const dx1 = v1.x - o.x, - dy1 = v1.y - o.y, - dx2 = v2.x - o.x, - dy2 = v2.y - o.y, - cross = dx1 * dy2 - dy1 * dx2, - dot = dx1 * dx2 + dy1 * dy2; - return atan2(cross, dot); - }, - - // round as string, to avoid rounding errors - round: function (v, d) { - const s = "" + v; - const pos = s.indexOf("."); - return parseFloat(s.substring(0, pos + 1 + d)); - }, - - dist: function (p1, p2) { - const dx = p1.x - p2.x, - dy = p1.y - p2.y; - return sqrt$1(dx * dx + dy * dy); - }, - - closest: function (LUT, point) { - let mdist = pow(2, 63), - mpos, - d; - LUT.forEach(function (p, idx) { - d = utils.dist(point, p); - if (d < mdist) { - mdist = d; - mpos = idx; - } - }); - return { mdist: mdist, mpos: mpos }; - }, - - abcratio: function (t, n) { - // see ratio(t) note on http://pomax.github.io/bezierinfo/#abc - if (n !== 2 && n !== 3) { - return false; - } - if (typeof t === "undefined") { - t = 0.5; - } else if (t === 0 || t === 1) { - return t; - } - const bottom = pow(t, n) + pow(1 - t, n), - top = bottom - 1; - return abs$1(top / bottom); - }, - - projectionratio: function (t, n) { - // see u(t) note on http://pomax.github.io/bezierinfo/#abc - if (n !== 2 && n !== 3) { - return false; - } - if (typeof t === "undefined") { - t = 0.5; - } else if (t === 0 || t === 1) { - return t; - } - const top = pow(1 - t, n), - bottom = pow(t, n) + top; - return top / bottom; - }, - - lli8: function (x1, y1, x2, y2, x3, y3, x4, y4) { - const nx = - (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4), - ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4), - d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); - if (d == 0) { - return false; - } - return { x: nx / d, y: ny / d }; - }, - - lli4: function (p1, p2, p3, p4) { - const x1 = p1.x, - y1 = p1.y, - x2 = p2.x, - y2 = p2.y, - x3 = p3.x, - y3 = p3.y, - x4 = p4.x, - y4 = p4.y; - return utils.lli8(x1, y1, x2, y2, x3, y3, x4, y4); - }, - - lli: function (v1, v2) { - return utils.lli4(v1, v1.c, v2, v2.c); - }, - - makeline: function (p1, p2) { - return new Bezier( - p1.x, - p1.y, - (p1.x + p2.x) / 2, - (p1.y + p2.y) / 2, - p2.x, - p2.y - ); - }, - - findbbox: function (sections) { - let mx = nMax, - my = nMax, - MX = nMin, - MY = nMin; - sections.forEach(function (s) { - const bbox = s.bbox(); - if (mx > bbox.x.min) mx = bbox.x.min; - if (my > bbox.y.min) my = bbox.y.min; - if (MX < bbox.x.max) MX = bbox.x.max; - if (MY < bbox.y.max) MY = bbox.y.max; - }); - return { - x: { min: mx, mid: (mx + MX) / 2, max: MX, size: MX - mx }, - y: { min: my, mid: (my + MY) / 2, max: MY, size: MY - my }, - }; - }, - - shapeintersections: function ( - s1, - bbox1, - s2, - bbox2, - curveIntersectionThreshold - ) { - if (!utils.bboxoverlap(bbox1, bbox2)) return []; - const intersections = []; - const a1 = [s1.startcap, s1.forward, s1.back, s1.endcap]; - const a2 = [s2.startcap, s2.forward, s2.back, s2.endcap]; - a1.forEach(function (l1) { - if (l1.virtual) return; - a2.forEach(function (l2) { - if (l2.virtual) return; - const iss = l1.intersects(l2, curveIntersectionThreshold); - if (iss.length > 0) { - iss.c1 = l1; - iss.c2 = l2; - iss.s1 = s1; - iss.s2 = s2; - intersections.push(iss); - } - }); - }); - return intersections; - }, - - makeshape: function (forward, back, curveIntersectionThreshold) { - const bpl = back.points.length; - const fpl = forward.points.length; - const start = utils.makeline(back.points[bpl - 1], forward.points[0]); - const end = utils.makeline(forward.points[fpl - 1], back.points[0]); - const shape = { - startcap: start, - forward: forward, - back: back, - endcap: end, - bbox: utils.findbbox([start, forward, back, end]), - }; - shape.intersections = function (s2) { - return utils.shapeintersections( - shape, - shape.bbox, - s2, - s2.bbox, - curveIntersectionThreshold - ); - }; - return shape; - }, - - getminmax: function (curve, d, list) { - if (!list) return { min: 0, max: 0 }; - let min = nMax, - max = nMin, - t, - c; - if (list.indexOf(0) === -1) { - list = [0].concat(list); - } - if (list.indexOf(1) === -1) { - list.push(1); - } - for (let i = 0, len = list.length; i < len; i++) { - t = list[i]; - c = curve.get(t); - if (c[d] < min) { - min = c[d]; - } - if (c[d] > max) { - max = c[d]; - } - } - return { min: min, mid: (min + max) / 2, max: max, size: max - min }; - }, - - align: function (points, line) { - const tx = line.p1.x, - ty = line.p1.y, - a = -atan2(line.p2.y - ty, line.p2.x - tx), - d = function (v) { - return { - x: (v.x - tx) * cos$1(a) - (v.y - ty) * sin$1(a), - y: (v.x - tx) * sin$1(a) + (v.y - ty) * cos$1(a), - }; - }; - return points.map(d); - }, - - roots: function (points, line) { - line = line || { p1: { x: 0, y: 0 }, p2: { x: 1, y: 0 } }; - - const order = points.length - 1; - const aligned = utils.align(points, line); - const reduce = function (t) { - return 0 <= t && t <= 1; - }; - - if (order === 2) { - const a = aligned[0].y, - b = aligned[1].y, - c = aligned[2].y, - d = a - 2 * b + c; - if (d !== 0) { - const m1 = -sqrt$1(b * b - a * c), - m2 = -a + b, - v1 = -(m1 + m2) / d, - v2 = -(-m1 + m2) / d; - return [v1, v2].filter(reduce); - } else if (b !== c && d === 0) { - return [(2 * b - c) / (2 * b - 2 * c)].filter(reduce); - } - return []; - } - - // see http://www.trans4mind.com/personal_development/mathematics/polynomials/cubicAlgebra.htm - const pa = aligned[0].y, - pb = aligned[1].y, - pc = aligned[2].y, - pd = aligned[3].y; - - let d = -pa + 3 * pb - 3 * pc + pd, - a = 3 * pa - 6 * pb + 3 * pc, - b = -3 * pa + 3 * pb, - c = pa; - - if (utils.approximately(d, 0)) { - // this is not a cubic curve. - if (utils.approximately(a, 0)) { - // in fact, this is not a quadratic curve either. - if (utils.approximately(b, 0)) { - // in fact in fact, there are no solutions. - return []; - } - // linear solution: - return [-c / b].filter(reduce); - } - // quadratic solution: - const q = sqrt$1(b * b - 4 * a * c), - a2 = 2 * a; - return [(q - b) / a2, (-b - q) / a2].filter(reduce); - } - - // at this point, we know we need a cubic solution: - - a /= d; - b /= d; - c /= d; - - const p = (3 * b - a * a) / 3, - p3 = p / 3, - q = (2 * a * a * a - 9 * a * b + 27 * c) / 27, - q2 = q / 2, - discriminant = q2 * q2 + p3 * p3 * p3; - - let u1, v1, x1, x2, x3; - if (discriminant < 0) { - const mp3 = -p / 3, - mp33 = mp3 * mp3 * mp3, - r = sqrt$1(mp33), - t = -q / (2 * r), - cosphi = t < -1 ? -1 : t > 1 ? 1 : t, - phi = acos$1(cosphi), - crtr = crt(r), - t1 = 2 * crtr; - x1 = t1 * cos$1(phi / 3) - a / 3; - x2 = t1 * cos$1((phi + tau) / 3) - a / 3; - x3 = t1 * cos$1((phi + 2 * tau) / 3) - a / 3; - return [x1, x2, x3].filter(reduce); - } else if (discriminant === 0) { - u1 = q2 < 0 ? crt(-q2) : -crt(q2); - x1 = 2 * u1 - a / 3; - x2 = -u1 - a / 3; - return [x1, x2].filter(reduce); - } else { - const sd = sqrt$1(discriminant); - u1 = crt(-q2 + sd); - v1 = crt(q2 + sd); - return [u1 - v1 - a / 3].filter(reduce); - } - }, - - droots: function (p) { - // quadratic roots are easy - if (p.length === 3) { - const a = p[0], - b = p[1], - c = p[2], - d = a - 2 * b + c; - if (d !== 0) { - const m1 = -sqrt$1(b * b - a * c), - m2 = -a + b, - v1 = -(m1 + m2) / d, - v2 = -(-m1 + m2) / d; - return [v1, v2]; - } else if (b !== c && d === 0) { - return [(2 * b - c) / (2 * (b - c))]; - } - return []; - } - - // linear roots are even easier - if (p.length === 2) { - const a = p[0], - b = p[1]; - if (a !== b) { - return [a / (a - b)]; - } - return []; - } - - return []; - }, - - curvature: function (t, d1, d2, _3d, kOnly) { - let num, - dnm, - adk, - dk, - k = 0, - r = 0; - - // - // We're using the following formula for curvature: - // - // x'y" - y'x" - // k(t) = ------------------ - // (x'² + y'²)^(3/2) - // - // from https://en.wikipedia.org/wiki/Radius_of_curvature#Definition - // - // With it corresponding 3D counterpart: - // - // sqrt( (y'z" - y"z')² + (z'x" - z"x')² + (x'y" - x"y')²) - // k(t) = ------------------------------------------------------- - // (x'² + y'² + z'²)^(3/2) - // - - const d = utils.compute(t, d1); - const dd = utils.compute(t, d2); - const qdsum = d.x * d.x + d.y * d.y; - - if (_3d) { - num = sqrt$1( - pow(d.y * dd.z - dd.y * d.z, 2) + - pow(d.z * dd.x - dd.z * d.x, 2) + - pow(d.x * dd.y - dd.x * d.y, 2) - ); - dnm = pow(qdsum + d.z * d.z, 3 / 2); - } else { - num = d.x * dd.y - d.y * dd.x; - dnm = pow(qdsum, 3 / 2); - } - - if (num === 0 || dnm === 0) { - return { k: 0, r: 0 }; - } - - k = num / dnm; - r = dnm / num; - - // We're also computing the derivative of kappa, because - // there is value in knowing the rate of change for the - // curvature along the curve. And we're just going to - // ballpark it based on an epsilon. - if (!kOnly) { - // compute k'(t) based on the interval before, and after it, - // to at least try to not introduce forward/backward pass bias. - const pk = utils.curvature(t - 0.001, d1, d2, _3d, true).k; - const nk = utils.curvature(t + 0.001, d1, d2, _3d, true).k; - dk = (nk - k + (k - pk)) / 2; - adk = (abs$1(nk - k) + abs$1(k - pk)) / 2; - } - - return { k: k, r: r, dk: dk, adk: adk }; - }, - - inflections: function (points) { - if (points.length < 4) return []; - - // FIXME: TODO: add in inflection abstraction for quartic+ curves? - - const p = utils.align(points, { p1: points[0], p2: points.slice(-1)[0] }), - a = p[2].x * p[1].y, - b = p[3].x * p[1].y, - c = p[1].x * p[2].y, - d = p[3].x * p[2].y, - v1 = 18 * (-3 * a + 2 * b + 3 * c - d), - v2 = 18 * (3 * a - b - 3 * c), - v3 = 18 * (c - a); - - if (utils.approximately(v1, 0)) { - if (!utils.approximately(v2, 0)) { - let t = -v3 / v2; - if (0 <= t && t <= 1) return [t]; - } - return []; - } - - const d2 = 2 * v1; - - if (utils.approximately(d2, 0)) return []; - - const trm = v2 * v2 - 4 * v1 * v3; - - if (trm < 0) return []; - - const sq = Math.sqrt(trm); - - return [(sq - v2) / d2, -(v2 + sq) / d2].filter(function (r) { - return 0 <= r && r <= 1; - }); - }, - - bboxoverlap: function (b1, b2) { - const dims = ["x", "y"], - len = dims.length; - - for (let i = 0, dim, l, t, d; i < len; i++) { - dim = dims[i]; - l = b1[dim].mid; - t = b2[dim].mid; - d = (b1[dim].size + b2[dim].size) / 2; - if (abs$1(l - t) >= d) return false; - } - return true; - }, - - expandbox: function (bbox, _bbox) { - if (_bbox.x.min < bbox.x.min) { - bbox.x.min = _bbox.x.min; - } - if (_bbox.y.min < bbox.y.min) { - bbox.y.min = _bbox.y.min; - } - if (_bbox.z && _bbox.z.min < bbox.z.min) { - bbox.z.min = _bbox.z.min; - } - if (_bbox.x.max > bbox.x.max) { - bbox.x.max = _bbox.x.max; - } - if (_bbox.y.max > bbox.y.max) { - bbox.y.max = _bbox.y.max; - } - if (_bbox.z && _bbox.z.max > bbox.z.max) { - bbox.z.max = _bbox.z.max; - } - bbox.x.mid = (bbox.x.min + bbox.x.max) / 2; - bbox.y.mid = (bbox.y.min + bbox.y.max) / 2; - if (bbox.z) { - bbox.z.mid = (bbox.z.min + bbox.z.max) / 2; - } - bbox.x.size = bbox.x.max - bbox.x.min; - bbox.y.size = bbox.y.max - bbox.y.min; - if (bbox.z) { - bbox.z.size = bbox.z.max - bbox.z.min; - } - }, - - pairiteration: function (c1, c2, curveIntersectionThreshold) { - const c1b = c1.bbox(), - c2b = c2.bbox(), - r = 100000, - threshold = curveIntersectionThreshold || 0.5; - - if ( - c1b.x.size + c1b.y.size < threshold && - c2b.x.size + c2b.y.size < threshold - ) { - return [ - (((r * (c1._t1 + c1._t2)) / 2) | 0) / r + - "/" + - (((r * (c2._t1 + c2._t2)) / 2) | 0) / r, - ]; - } - - let cc1 = c1.split(0.5), - cc2 = c2.split(0.5), - pairs = [ - { left: cc1.left, right: cc2.left }, - { left: cc1.left, right: cc2.right }, - { left: cc1.right, right: cc2.right }, - { left: cc1.right, right: cc2.left }, - ]; - - pairs = pairs.filter(function (pair) { - return utils.bboxoverlap(pair.left.bbox(), pair.right.bbox()); - }); - - let results = []; - - if (pairs.length === 0) return results; - - pairs.forEach(function (pair) { - results = results.concat( - utils.pairiteration(pair.left, pair.right, threshold) - ); - }); - - results = results.filter(function (v, i) { - return results.indexOf(v) === i; - }); - - return results; - }, - - getccenter: function (p1, p2, p3) { - const dx1 = p2.x - p1.x, - dy1 = p2.y - p1.y, - dx2 = p3.x - p2.x, - dy2 = p3.y - p2.y, - dx1p = dx1 * cos$1(quart) - dy1 * sin$1(quart), - dy1p = dx1 * sin$1(quart) + dy1 * cos$1(quart), - dx2p = dx2 * cos$1(quart) - dy2 * sin$1(quart), - dy2p = dx2 * sin$1(quart) + dy2 * cos$1(quart), - // chord midpoints - mx1 = (p1.x + p2.x) / 2, - my1 = (p1.y + p2.y) / 2, - mx2 = (p2.x + p3.x) / 2, - my2 = (p2.y + p3.y) / 2, - // midpoint offsets - mx1n = mx1 + dx1p, - my1n = my1 + dy1p, - mx2n = mx2 + dx2p, - my2n = my2 + dy2p, - // intersection of these lines: - arc = utils.lli8(mx1, my1, mx1n, my1n, mx2, my2, mx2n, my2n), - r = utils.dist(arc, p1); - - // arc start/end values, over mid point: - let s = atan2(p1.y - arc.y, p1.x - arc.x), - m = atan2(p2.y - arc.y, p2.x - arc.x), - e = atan2(p3.y - arc.y, p3.x - arc.x), - _; - - // determine arc direction (cw/ccw correction) - if (s < e) { - // if s m || m > e) { - s += tau; - } - if (s > e) { - _ = e; - e = s; - s = _; - } - } else { - // if e 4) { - if (arguments.length !== 1) { - throw new Error( - "Only new Bezier(point[]) is accepted for 4th and higher order curves" - ); - } - higher = true; - } - } else { - if (len !== 6 && len !== 8 && len !== 9 && len !== 12) { - if (arguments.length !== 1) { - throw new Error( - "Only new Bezier(point[]) is accepted for 4th and higher order curves" - ); - } - } - } - - const _3d = (this._3d = - (!higher && (len === 9 || len === 12)) || - (coords && coords[0] && typeof coords[0].z !== "undefined")); - - const points = (this.points = []); - for (let idx = 0, step = _3d ? 3 : 2; idx < len; idx += step) { - var point = { - x: args[idx], - y: args[idx + 1], - }; - if (_3d) { - point.z = args[idx + 2]; - } - points.push(point); - } - const order = (this.order = points.length - 1); - - const dims = (this.dims = ["x", "y"]); - if (_3d) dims.push("z"); - this.dimlen = dims.length; - - // is this curve, practically speaking, a straight line? - const aligned = utils.align(points, { p1: points[0], p2: points[order] }); - const baselength = utils.dist(points[0], points[order]); - this._linear = aligned.reduce((t, p) => t + abs(p.y), 0) < baselength / 50; - - this._lut = []; - this._t1 = 0; - this._t2 = 1; - this.update(); - } - - static quadraticFromPoints(p1, p2, p3, t) { - if (typeof t === "undefined") { - t = 0.5; - } - // shortcuts, although they're really dumb - if (t === 0) { - return new Bezier(p2, p2, p3); - } - if (t === 1) { - return new Bezier(p1, p2, p2); - } - // real fitting. - const abc = Bezier.getABC(2, p1, p2, p3, t); - return new Bezier(p1, abc.A, p3); - } - - static cubicFromPoints(S, B, E, t, d1) { - if (typeof t === "undefined") { - t = 0.5; - } - const abc = Bezier.getABC(3, S, B, E, t); - if (typeof d1 === "undefined") { - d1 = utils.dist(B, abc.C); - } - const d2 = (d1 * (1 - t)) / t; - - const selen = utils.dist(S, E), - lx = (E.x - S.x) / selen, - ly = (E.y - S.y) / selen, - bx1 = d1 * lx, - by1 = d1 * ly, - bx2 = d2 * lx, - by2 = d2 * ly; - // derivation of new hull coordinates - const e1 = { x: B.x - bx1, y: B.y - by1 }, - e2 = { x: B.x + bx2, y: B.y + by2 }, - A = abc.A, - v1 = { x: A.x + (e1.x - A.x) / (1 - t), y: A.y + (e1.y - A.y) / (1 - t) }, - v2 = { x: A.x + (e2.x - A.x) / t, y: A.y + (e2.y - A.y) / t }, - nc1 = { x: S.x + (v1.x - S.x) / t, y: S.y + (v1.y - S.y) / t }, - nc2 = { - x: E.x + (v2.x - E.x) / (1 - t), - y: E.y + (v2.y - E.y) / (1 - t), - }; - // ...done - return new Bezier(S, nc1, nc2, E); - } - - static getUtils() { - return utils; - } - - getUtils() { - return Bezier.getUtils(); - } - - static get PolyBezier() { - return PolyBezier; - } - - valueOf() { - return this.toString(); - } - - toString() { - return utils.pointsToString(this.points); - } - - toSVG() { - if (this._3d) return false; - const p = this.points, - x = p[0].x, - y = p[0].y, - s = ["M", x, y, this.order === 2 ? "Q" : "C"]; - for (let i = 1, last = p.length; i < last; i++) { - s.push(p[i].x); - s.push(p[i].y); - } - return s.join(" "); - } - - setRatios(ratios) { - if (ratios.length !== this.points.length) { - throw new Error("incorrect number of ratio values"); - } - this.ratios = ratios; - this._lut = []; // invalidate any precomputed LUT - } - - verify() { - const print = this.coordDigest(); - if (print !== this._print) { - this._print = print; - this.update(); - } - } - - coordDigest() { - return this.points - .map(function (c, pos) { - return "" + pos + c.x + c.y + (c.z ? c.z : 0); - }) - .join(""); - } - - update() { - // invalidate any precomputed LUT - this._lut = []; - this.dpoints = utils.derive(this.points, this._3d); - this.computedirection(); - } - - computedirection() { - const points = this.points; - const angle = utils.angle(points[0], points[this.order], points[1]); - this.clockwise = angle > 0; - } - - length() { - return utils.length(this.derivative.bind(this)); - } - - static getABC(order = 2, S, B, E, t = 0.5) { - const u = utils.projectionratio(t, order), - um = 1 - u, - C = { - x: u * S.x + um * E.x, - y: u * S.y + um * E.y, - }, - s = utils.abcratio(t, order), - A = { - x: B.x + (B.x - C.x) / s, - y: B.y + (B.y - C.y) / s, - }; - return { A, B, C, S, E }; - } - - getABC(t, B) { - B = B || this.get(t); - let S = this.points[0]; - let E = this.points[this.order]; - return Bezier.getABC(this.order, S, B, E, t); - } - - getLUT(steps) { - this.verify(); - steps = steps || 100; - if (this._lut.length === steps + 1) { - return this._lut; - } - this._lut = []; - // n steps means n+1 points - steps++; - this._lut = []; - for (let i = 0, p, t; i < steps; i++) { - t = i / (steps - 1); - p = this.compute(t); - p.t = t; - this._lut.push(p); - } - return this._lut; - } - - on(point, error) { - error = error || 5; - const lut = this.getLUT(), - hits = []; - for (let i = 0, c, t = 0; i < lut.length; i++) { - c = lut[i]; - if (utils.dist(c, point) < error) { - hits.push(c); - t += i / lut.length; - } - } - if (!hits.length) return false; - return (t /= hits.length); - } - - project(point) { - // step 1: coarse check - const LUT = this.getLUT(), - l = LUT.length - 1, - closest = utils.closest(LUT, point), - mpos = closest.mpos, - t1 = (mpos - 1) / l, - t2 = (mpos + 1) / l, - step = 0.1 / l; - - // step 2: fine check - let mdist = closest.mdist, - t = t1, - ft = t, - p; - mdist += 1; - for (let d; t < t2 + step; t += step) { - p = this.compute(t); - d = utils.dist(point, p); - if (d < mdist) { - mdist = d; - ft = t; - } - } - ft = ft < 0 ? 0 : ft > 1 ? 1 : ft; - p = this.compute(ft); - p.t = ft; - p.d = mdist; - return p; - } - - get(t) { - return this.compute(t); - } - - point(idx) { - return this.points[idx]; - } - - compute(t) { - if (this.ratios) { - return utils.computeWithRatios(t, this.points, this.ratios, this._3d); - } - return utils.compute(t, this.points, this._3d, this.ratios); - } - - raise() { - const p = this.points, - np = [p[0]], - k = p.length; - for (let i = 1, pi, pim; i < k; i++) { - pi = p[i]; - pim = p[i - 1]; - np[i] = { - x: ((k - i) / k) * pi.x + (i / k) * pim.x, - y: ((k - i) / k) * pi.y + (i / k) * pim.y, - }; - } - np[k] = p[k - 1]; - return new Bezier(np); - } - - derivative(t) { - return utils.compute(t, this.dpoints[0], this._3d); - } - - dderivative(t) { - return utils.compute(t, this.dpoints[1], this._3d); - } - - align() { - let p = this.points; - return new Bezier(utils.align(p, { p1: p[0], p2: p[p.length - 1] })); - } - - curvature(t) { - return utils.curvature(t, this.dpoints[0], this.dpoints[1], this._3d); - } - - inflections() { - return utils.inflections(this.points); - } - - normal(t) { - return this._3d ? this.__normal3(t) : this.__normal2(t); - } - - __normal2(t) { - const d = this.derivative(t); - const q = sqrt(d.x * d.x + d.y * d.y); - return { t, x: -d.y / q, y: d.x / q }; - } - - __normal3(t) { - // see http://stackoverflow.com/questions/25453159 - const r1 = this.derivative(t), - r2 = this.derivative(t + 0.01), - q1 = sqrt(r1.x * r1.x + r1.y * r1.y + r1.z * r1.z), - q2 = sqrt(r2.x * r2.x + r2.y * r2.y + r2.z * r2.z); - r1.x /= q1; - r1.y /= q1; - r1.z /= q1; - r2.x /= q2; - r2.y /= q2; - r2.z /= q2; - // cross product - const c = { - x: r2.y * r1.z - r2.z * r1.y, - y: r2.z * r1.x - r2.x * r1.z, - z: r2.x * r1.y - r2.y * r1.x, - }; - const m = sqrt(c.x * c.x + c.y * c.y + c.z * c.z); - c.x /= m; - c.y /= m; - c.z /= m; - // rotation matrix - const R = [ - c.x * c.x, - c.x * c.y - c.z, - c.x * c.z + c.y, - c.x * c.y + c.z, - c.y * c.y, - c.y * c.z - c.x, - c.x * c.z - c.y, - c.y * c.z + c.x, - c.z * c.z, - ]; - // normal vector: - const n = { - t, - x: R[0] * r1.x + R[1] * r1.y + R[2] * r1.z, - y: R[3] * r1.x + R[4] * r1.y + R[5] * r1.z, - z: R[6] * r1.x + R[7] * r1.y + R[8] * r1.z, - }; - return n; - } - - hull(t) { - let p = this.points, - _p = [], - q = [], - idx = 0; - q[idx++] = p[0]; - q[idx++] = p[1]; - q[idx++] = p[2]; - if (this.order === 3) { - q[idx++] = p[3]; - } - // we lerp between all points at each iteration, until we have 1 point left. - while (p.length > 1) { - _p = []; - for (let i = 0, pt, l = p.length - 1; i < l; i++) { - pt = utils.lerp(t, p[i], p[i + 1]); - q[idx++] = pt; - _p.push(pt); - } - p = _p; - } - return q; - } - - split(t1, t2) { - // shortcuts - if (t1 === 0 && !!t2) { - return this.split(t2).left; - } - if (t2 === 1) { - return this.split(t1).right; - } - - // no shortcut: use "de Casteljau" iteration. - const q = this.hull(t1); - const result = { - left: - this.order === 2 - ? new Bezier([q[0], q[3], q[5]]) - : new Bezier([q[0], q[4], q[7], q[9]]), - right: - this.order === 2 - ? new Bezier([q[5], q[4], q[2]]) - : new Bezier([q[9], q[8], q[6], q[3]]), - span: q, - }; - - // make sure we bind _t1/_t2 information! - result.left._t1 = utils.map(0, 0, 1, this._t1, this._t2); - result.left._t2 = utils.map(t1, 0, 1, this._t1, this._t2); - result.right._t1 = utils.map(t1, 0, 1, this._t1, this._t2); - result.right._t2 = utils.map(1, 0, 1, this._t1, this._t2); - - // if we have no t2, we're done - if (!t2) { - return result; - } - - // if we have a t2, split again: - t2 = utils.map(t2, t1, 1, 0, 1); - return result.right.split(t2).left; - } - - extrema() { - const result = {}; - let roots = []; - - this.dims.forEach( - function (dim) { - let mfn = function (v) { - return v[dim]; - }; - let p = this.dpoints[0].map(mfn); - result[dim] = utils.droots(p); - if (this.order === 3) { - p = this.dpoints[1].map(mfn); - result[dim] = result[dim].concat(utils.droots(p)); - } - result[dim] = result[dim].filter(function (t) { - return t >= 0 && t <= 1; - }); - roots = roots.concat(result[dim].sort(utils.numberSort)); - }.bind(this) - ); - - result.values = roots.sort(utils.numberSort).filter(function (v, idx) { - return roots.indexOf(v) === idx; - }); - - return result; - } - - bbox() { - const extrema = this.extrema(), - result = {}; - this.dims.forEach( - function (d) { - result[d] = utils.getminmax(this, d, extrema[d]); - }.bind(this) - ); - return result; - } - - overlaps(curve) { - const lbbox = this.bbox(), - tbbox = curve.bbox(); - return utils.bboxoverlap(lbbox, tbbox); - } - - offset(t, d) { - if (typeof d !== "undefined") { - const c = this.get(t), - n = this.normal(t); - const ret = { - c: c, - n: n, - x: c.x + n.x * d, - y: c.y + n.y * d, - }; - if (this._3d) { - ret.z = c.z + n.z * d; - } - return ret; - } - if (this._linear) { - const nv = this.normal(0), - coords = this.points.map(function (p) { - const ret = { - x: p.x + t * nv.x, - y: p.y + t * nv.y, - }; - if (p.z && nv.z) { - ret.z = p.z + t * nv.z; - } - return ret; - }); - return [new Bezier(coords)]; - } - return this.reduce().map(function (s) { - if (s._linear) { - return s.offset(t)[0]; - } - return s.scale(t); - }); - } - - simple() { - if (this.order === 3) { - const a1 = utils.angle(this.points[0], this.points[3], this.points[1]); - const a2 = utils.angle(this.points[0], this.points[3], this.points[2]); - if ((a1 > 0 && a2 < 0) || (a1 < 0 && a2 > 0)) return false; - } - const n1 = this.normal(0); - const n2 = this.normal(1); - let s = n1.x * n2.x + n1.y * n2.y; - if (this._3d) { - s += n1.z * n2.z; - } - return abs(acos(s)) < pi / 3; - } - - reduce() { - // TODO: examine these var types in more detail... - let i, - t1 = 0, - t2 = 0, - step = 0.01, - segment, - pass1 = [], - pass2 = []; - // first pass: split on extrema - let extrema = this.extrema().values; - if (extrema.indexOf(0) === -1) { - extrema = [0].concat(extrema); - } - if (extrema.indexOf(1) === -1) { - extrema.push(1); - } - - for (t1 = extrema[0], i = 1; i < extrema.length; i++) { - t2 = extrema[i]; - segment = this.split(t1, t2); - segment._t1 = t1; - segment._t2 = t2; - pass1.push(segment); - t1 = t2; - } - - // second pass: further reduce these segments to simple segments - pass1.forEach(function (p1) { - t1 = 0; - t2 = 0; - while (t2 <= 1) { - for (t2 = t1 + step; t2 <= 1 + step; t2 += step) { - segment = p1.split(t1, t2); - if (!segment.simple()) { - t2 -= step; - if (abs(t1 - t2) < step) { - // we can never form a reduction - return []; - } - segment = p1.split(t1, t2); - segment._t1 = utils.map(t1, 0, 1, p1._t1, p1._t2); - segment._t2 = utils.map(t2, 0, 1, p1._t1, p1._t2); - pass2.push(segment); - t1 = t2; - break; - } - } - } - if (t1 < 1) { - segment = p1.split(t1, 1); - segment._t1 = utils.map(t1, 0, 1, p1._t1, p1._t2); - segment._t2 = p1._t2; - pass2.push(segment); - } - }); - return pass2; - } - - translate(v, d1, d2) { - d2 = typeof d2 === "number" ? d2 : d1; - - // TODO: make this take curves with control points outside - // of the start-end interval into account - - const o = this.order; - let d = this.points.map((_, i) => (1 - i / o) * d1 + (i / o) * d2); - return new Bezier( - this.points.map((p, i) => ({ - x: p.x + v.x * d[i], - y: p.y + v.y * d[i], - })) - ); - } - - scale(d) { - const order = this.order; - let distanceFn = false; - if (typeof d === "function") { - distanceFn = d; - } - if (distanceFn && order === 2) { - return this.raise().scale(distanceFn); - } - - // TODO: add special handling for non-linear degenerate curves. - - const clockwise = this.clockwise; - const points = this.points; - - if (this._linear) { - return this.translate( - this.normal(0), - distanceFn ? distanceFn(0) : d, - distanceFn ? distanceFn(1) : d - ); - } - - const r1 = distanceFn ? distanceFn(0) : d; - const r2 = distanceFn ? distanceFn(1) : d; - const v = [this.offset(0, 10), this.offset(1, 10)]; - const np = []; - const o = utils.lli4(v[0], v[0].c, v[1], v[1].c); - - if (!o) { - throw new Error("cannot scale this curve. Try reducing it first."); - } - - // move all points by distance 'd' wrt the origin 'o', - // and move end points by fixed distance along normal. - [0, 1].forEach(function (t) { - const p = (np[t * order] = utils.copy(points[t * order])); - p.x += (t ? r2 : r1) * v[t].n.x; - p.y += (t ? r2 : r1) * v[t].n.y; - }); - - if (!distanceFn) { - // move control points to lie on the intersection of the offset - // derivative vector, and the origin-through-control vector - [0, 1].forEach((t) => { - if (order === 2 && !!t) return; - const p = np[t * order]; - const d = this.derivative(t); - const p2 = { x: p.x + d.x, y: p.y + d.y }; - np[t + 1] = utils.lli4(p, p2, o, points[t + 1]); - }); - return new Bezier(np); - } - - // move control points by "however much necessary to - // ensure the correct tangent to endpoint". - [0, 1].forEach(function (t) { - if (order === 2 && !!t) return; - var p = points[t + 1]; - var ov = { - x: p.x - o.x, - y: p.y - o.y, - }; - var rc = distanceFn ? distanceFn((t + 1) / order) : d; - if (distanceFn && !clockwise) rc = -rc; - var m = sqrt(ov.x * ov.x + ov.y * ov.y); - ov.x /= m; - ov.y /= m; - np[t + 1] = { - x: p.x + rc * ov.x, - y: p.y + rc * ov.y, - }; - }); - return new Bezier(np); - } - - outline(d1, d2, d3, d4) { - d2 = d2 === undefined ? d1 : d2; - - if (this._linear) { - // TODO: find the actual extrema, because they might - // be before the start, or past the end. - - const n = this.normal(0); - const start = this.points[0]; - const end = this.points[this.points.length - 1]; - let s, mid, e; - - if (d3 === undefined) { - d3 = d1; - d4 = d2; - } - - s = { x: start.x + n.x * d1, y: start.y + n.y * d1 }; - e = { x: end.x + n.x * d3, y: end.y + n.y * d3 }; - mid = { x: (s.x + e.x) / 2, y: (s.y + e.y) / 2 }; - const fline = [s, mid, e]; - - s = { x: start.x - n.x * d2, y: start.y - n.y * d2 }; - e = { x: end.x - n.x * d4, y: end.y - n.y * d4 }; - mid = { x: (s.x + e.x) / 2, y: (s.y + e.y) / 2 }; - const bline = [e, mid, s]; - - const ls = utils.makeline(bline[2], fline[0]); - const le = utils.makeline(fline[2], bline[0]); - const segments = [ls, new Bezier(fline), le, new Bezier(bline)]; - return new PolyBezier(segments); - } - - const reduced = this.reduce(), - len = reduced.length, - fcurves = []; - - let bcurves = [], - p, - alen = 0, - tlen = this.length(); - - const graduated = typeof d3 !== "undefined" && typeof d4 !== "undefined"; - - function linearDistanceFunction(s, e, tlen, alen, slen) { - return function (v) { - const f1 = alen / tlen, - f2 = (alen + slen) / tlen, - d = e - s; - return utils.map(v, 0, 1, s + f1 * d, s + f2 * d); - }; - } - - // form curve oulines - reduced.forEach(function (segment) { - const slen = segment.length(); - if (graduated) { - fcurves.push( - segment.scale(linearDistanceFunction(d1, d3, tlen, alen, slen)) - ); - bcurves.push( - segment.scale(linearDistanceFunction(-d2, -d4, tlen, alen, slen)) - ); - } else { - fcurves.push(segment.scale(d1)); - bcurves.push(segment.scale(-d2)); - } - alen += slen; - }); - - // reverse the "return" outline - bcurves = bcurves - .map(function (s) { - p = s.points; - if (p[3]) { - s.points = [p[3], p[2], p[1], p[0]]; - } else { - s.points = [p[2], p[1], p[0]]; - } - return s; - }) - .reverse(); - - // form the endcaps as lines - const fs = fcurves[0].points[0], - fe = fcurves[len - 1].points[fcurves[len - 1].points.length - 1], - bs = bcurves[len - 1].points[bcurves[len - 1].points.length - 1], - be = bcurves[0].points[0], - ls = utils.makeline(bs, fs), - le = utils.makeline(fe, be), - segments = [ls].concat(fcurves).concat([le]).concat(bcurves); - - return new PolyBezier(segments); - } - - outlineshapes(d1, d2, curveIntersectionThreshold) { - d2 = d2 || d1; - const outline = this.outline(d1, d2).curves; - const shapes = []; - for (let i = 1, len = outline.length; i < len / 2; i++) { - const shape = utils.makeshape( - outline[i], - outline[len - i], - curveIntersectionThreshold - ); - shape.startcap.virtual = i > 1; - shape.endcap.virtual = i < len / 2 - 1; - shapes.push(shape); - } - return shapes; - } - - intersects(curve, curveIntersectionThreshold) { - if (!curve) return this.selfintersects(curveIntersectionThreshold); - if (curve.p1 && curve.p2) { - return this.lineIntersects(curve); - } - if (curve instanceof Bezier) { - curve = curve.reduce(); - } - return this.curveintersects( - this.reduce(), - curve, - curveIntersectionThreshold - ); - } - - lineIntersects(line) { - const mx = min(line.p1.x, line.p2.x), - my = min(line.p1.y, line.p2.y), - MX = max(line.p1.x, line.p2.x), - MY = max(line.p1.y, line.p2.y); - return utils.roots(this.points, line).filter((t) => { - var p = this.get(t); - return utils.between(p.x, mx, MX) && utils.between(p.y, my, MY); - }); - } - - selfintersects(curveIntersectionThreshold) { - // "simple" curves cannot intersect with their direct - // neighbour, so for each segment X we check whether - // it intersects [0:x-2][x+2:last]. - - const reduced = this.reduce(), - len = reduced.length - 2, - results = []; - - for (let i = 0, result, left, right; i < len; i++) { - left = reduced.slice(i, i + 1); - right = reduced.slice(i + 2); - result = this.curveintersects(left, right, curveIntersectionThreshold); - results.push(...result); - } - return results; - } - - curveintersects(c1, c2, curveIntersectionThreshold) { - const pairs = []; - // step 1: pair off any overlapping segments - c1.forEach(function (l) { - c2.forEach(function (r) { - if (l.overlaps(r)) { - pairs.push({ left: l, right: r }); - } - }); - }); - // step 2: for each pairing, run through the convergence algorithm. - let intersections = []; - pairs.forEach(function (pair) { - const result = utils.pairiteration( - pair.left, - pair.right, - curveIntersectionThreshold - ); - if (result.length > 0) { - intersections = intersections.concat(result); - } - }); - return intersections; - } - - arcs(errorThreshold) { - errorThreshold = errorThreshold || 0.5; - return this._iterate(errorThreshold, []); - } - - _error(pc, np1, s, e) { - const q = (e - s) / 4, - c1 = this.get(s + q), - c2 = this.get(e - q), - ref = utils.dist(pc, np1), - d1 = utils.dist(pc, c1), - d2 = utils.dist(pc, c2); - return abs(d1 - ref) + abs(d2 - ref); - } - - _iterate(errorThreshold, circles) { - let t_s = 0, - t_e = 1, - safety; - // we do a binary search to find the "good `t` closest to no-longer-good" - do { - safety = 0; - - // step 1: start with the maximum possible arc - t_e = 1; - - // points: - let np1 = this.get(t_s), - np2, - np3, - arc, - prev_arc; - - // booleans: - let curr_good = false, - prev_good = false, - done; - - // numbers: - let t_m = t_e, - prev_e = 1; - - // step 2: find the best possible arc - do { - prev_good = curr_good; - prev_arc = arc; - t_m = (t_s + t_e) / 2; - - np2 = this.get(t_m); - np3 = this.get(t_e); - - arc = utils.getccenter(np1, np2, np3); - - //also save the t values - arc.interval = { - start: t_s, - end: t_e, - }; - - let error = this._error(arc, np1, t_s, t_e); - curr_good = error <= errorThreshold; - - done = prev_good && !curr_good; - if (!done) prev_e = t_e; - - // this arc is fine: we can move 'e' up to see if we can find a wider arc - if (curr_good) { - // if e is already at max, then we're done for this arc. - if (t_e >= 1) { - // make sure we cap at t=1 - arc.interval.end = prev_e = 1; - prev_arc = arc; - // if we capped the arc segment to t=1 we also need to make sure that - // the arc's end angle is correct with respect to the bezier end point. - if (t_e > 1) { - let d = { - x: arc.x + arc.r * cos(arc.e), - y: arc.y + arc.r * sin(arc.e), - }; - arc.e += utils.angle({ x: arc.x, y: arc.y }, d, this.get(1)); - } - break; - } - // if not, move it up by half the iteration distance - t_e = t_e + (t_e - t_s) / 2; - } else { - // this is a bad arc: we need to move 'e' down to find a good arc - t_e = t_m; - } - } while (!done && safety++ < 100); - - if (safety >= 100) { - break; - } - - // console.log("L835: [F] arc found", t_s, prev_e, prev_arc.x, prev_arc.y, prev_arc.s, prev_arc.e); - - prev_arc = prev_arc ? prev_arc : arc; - circles.push(prev_arc); - t_s = prev_e; - } while (t_e < 1); - return circles; - } - } - - function _iterableToArrayLimit(arr, i) { - var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; - if (null != _i) { - var _s, - _e, - _x, - _r, - _arr = [], - _n = !0, - _d = !1; - try { - if (_x = (_i = _i.call(arr)).next, 0 === i) { - if (Object(_i) !== _i) return; - _n = !1; - } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); - } catch (err) { - _d = !0, _e = err; - } finally { - try { - if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; - } finally { - if (_d) throw _e; - } - } - return _arr; - } - } - function _objectWithoutPropertiesLoose(source, excluded) { - if (source == null) return {}; - var target = {}; - var sourceKeys = Object.keys(source); - var key, i; - for (i = 0; i < sourceKeys.length; i++) { - key = sourceKeys[i]; - if (excluded.indexOf(key) >= 0) continue; - target[key] = source[key]; - } - return target; - } - function _objectWithoutProperties(source, excluded) { - if (source == null) return {}; - var target = _objectWithoutPropertiesLoose(source, excluded); - var key, i; - if (Object.getOwnPropertySymbols) { - var sourceSymbolKeys = Object.getOwnPropertySymbols(source); - for (i = 0; i < sourceSymbolKeys.length; i++) { - key = sourceSymbolKeys[i]; - if (excluded.indexOf(key) >= 0) continue; - if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; - target[key] = source[key]; - } - } - return target; - } - function _slicedToArray(arr, i) { - return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); - } - function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); - } - function _arrayWithoutHoles(arr) { - if (Array.isArray(arr)) return _arrayLikeToArray(arr); - } - function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; - } - function _iterableToArray(iter) { - if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); - } - function _unsupportedIterableToArray(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); - } - function _arrayLikeToArray(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; - } - function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _toPrimitive(input, hint) { - if (typeof input !== "object" || input === null) return input; - var prim = input[Symbol.toPrimitive]; - if (prim !== undefined) { - var res = prim.call(input, hint || "default"); - if (typeof res !== "object") return res; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return (hint === "string" ? String : Number)(input); - } - function _toPropertyKey(arg) { - var key = _toPrimitive(arg, "string"); - return typeof key === "symbol" ? key : String(key); - } - - var index = (function () { - var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - var keyAccessors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; - var multiItem = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; - var flattenKeys = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - var keys = (keyAccessors instanceof Array ? keyAccessors.length ? keyAccessors : [undefined] : [keyAccessors]).map(function (key) { - return { - keyAccessor: key, - isProp: !(key instanceof Function) - }; - }); - var indexedResult = list.reduce(function (res, item) { - var iterObj = res; - var itemVal = item; - keys.forEach(function (_ref, idx) { - var keyAccessor = _ref.keyAccessor, - isProp = _ref.isProp; - var key; - if (isProp) { - var _itemVal = itemVal, - propVal = _itemVal[keyAccessor], - rest = _objectWithoutProperties(_itemVal, [keyAccessor].map(_toPropertyKey)); - key = propVal; - itemVal = rest; - } else { - key = keyAccessor(itemVal, idx); - } - if (idx + 1 < keys.length) { - if (!iterObj.hasOwnProperty(key)) { - iterObj[key] = {}; - } - iterObj = iterObj[key]; - } else { - // Leaf key - if (multiItem) { - if (!iterObj.hasOwnProperty(key)) { - iterObj[key] = []; - } - iterObj[key].push(itemVal); - } else { - iterObj[key] = itemVal; - } - } - }); - return res; - }, {}); - if (multiItem instanceof Function) { - // Reduce leaf multiple values - (function reduce(node) { - var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; - if (level === keys.length) { - Object.keys(node).forEach(function (k) { - return node[k] = multiItem(node[k]); - }); - } else { - Object.values(node).forEach(function (child) { - return reduce(child, level + 1); - }); - } - })(indexedResult); // IIFE - } - - var result = indexedResult; - if (flattenKeys) { - // flatten into array - result = []; - (function flatten(node) { - var accKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; - if (accKeys.length === keys.length) { - result.push({ - keys: accKeys, - vals: node - }); - } else { - Object.entries(node).forEach(function (_ref2) { - var _ref3 = _slicedToArray(_ref2, 2), - key = _ref3[0], - val = _ref3[1]; - return flatten(val, [].concat(_toConsumableArray(accKeys), [key])); - }); - } - })(indexedResult); //IIFE - - if (keyAccessors instanceof Array && keyAccessors.length === 0 && result.length === 1) { - // clear keys if there's no key accessors (single result) - result[0].keys = []; - } - } - return result; - }); - - function initRange(domain, range) { - switch (arguments.length) { - case 0: break; - case 1: this.range(domain); break; - default: this.range(range).domain(domain); break; - } - return this; - } - - const implicit = Symbol("implicit"); - - function ordinal() { - var index = new InternMap(), - domain = [], - range = [], - unknown = implicit; - - function scale(d) { - let i = index.get(d); - if (i === undefined) { - if (unknown !== implicit) return unknown; - index.set(d, i = domain.push(d) - 1); - } - return range[i % range.length]; - } - - scale.domain = function(_) { - if (!arguments.length) return domain.slice(); - domain = [], index = new InternMap(); - for (const value of _) { - if (index.has(value)) continue; - index.set(value, domain.push(value) - 1); - } - return scale; - }; - - scale.range = function(_) { - return arguments.length ? (range = Array.from(_), scale) : range.slice(); - }; - - scale.unknown = function(_) { - return arguments.length ? (unknown = _, scale) : unknown; - }; - - scale.copy = function() { - return ordinal(domain, range).unknown(unknown); - }; - - initRange.apply(scale, arguments); - - return scale; - } - - function colors(specifier) { - var n = specifier.length / 6 | 0, colors = new Array(n), i = 0; - while (i < n) colors[i] = "#" + specifier.slice(i * 6, ++i * 6); - return colors; - } - - var schemePaired = colors("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"); - - var autoColorScale = ordinal(schemePaired); - - // Autoset attribute colorField by colorByAccessor property - // If an object has already a color, don't set it - // Objects can be nodes or links - function autoColorObjects(objects, colorByAccessor, colorField) { - if (!colorByAccessor || typeof colorField !== 'string') return; - objects.filter(function (obj) { - return !obj[colorField]; - }).forEach(function (obj) { - obj[colorField] = autoColorScale(colorByAccessor(obj)); - }); - } - - function getDagDepths (_ref, idAccessor) { - var nodes = _ref.nodes, - links = _ref.links; - var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, - _ref2$nodeFilter = _ref2.nodeFilter, - nodeFilter = _ref2$nodeFilter === void 0 ? function () { - return true; - } : _ref2$nodeFilter, - _ref2$onLoopError = _ref2.onLoopError, - onLoopError = _ref2$onLoopError === void 0 ? function (loopIds) { - throw "Invalid DAG structure! Found cycle in node path: ".concat(loopIds.join(' -> '), "."); - } : _ref2$onLoopError; - // linked graph - var graph = {}; - nodes.forEach(function (node) { - return graph[idAccessor(node)] = { - data: node, - out: [], - depth: -1, - skip: !nodeFilter(node) - }; - }); - links.forEach(function (_ref3) { - var source = _ref3.source, - target = _ref3.target; - var sourceId = getNodeId(source); - var targetId = getNodeId(target); - if (!graph.hasOwnProperty(sourceId)) throw "Missing source node with id: ".concat(sourceId); - if (!graph.hasOwnProperty(targetId)) throw "Missing target node with id: ".concat(targetId); - var sourceNode = graph[sourceId]; - var targetNode = graph[targetId]; - sourceNode.out.push(targetNode); - function getNodeId(node) { - return _typeof$1(node) === 'object' ? idAccessor(node) : node; - } - }); - var foundLoops = []; - traverse(Object.values(graph)); - var nodeDepths = Object.assign.apply(Object, [{}].concat(_toConsumableArray$2(Object.entries(graph).filter(function (_ref4) { - var _ref5 = _slicedToArray$2(_ref4, 2), - node = _ref5[1]; - return !node.skip; - }).map(function (_ref6) { - var _ref7 = _slicedToArray$2(_ref6, 2), - id = _ref7[0], - node = _ref7[1]; - return _defineProperty({}, id, node.depth); - })))); - return nodeDepths; - function traverse(nodes) { - var nodeStack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; - var currentDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var _loop = function _loop() { - var node = nodes[i]; - if (nodeStack.indexOf(node) !== -1) { - var loop = [].concat(_toConsumableArray$2(nodeStack.slice(nodeStack.indexOf(node))), [node]).map(function (d) { - return idAccessor(d.data); - }); - if (!foundLoops.some(function (foundLoop) { - return foundLoop.length === loop.length && foundLoop.every(function (id, idx) { - return id === loop[idx]; - }); - })) { - foundLoops.push(loop); - onLoopError(loop); - } - return 1; // continue - } - if (currentDepth > node.depth) { - // Don't unnecessarily revisit chunks of the graph - node.depth = currentDepth; - traverse(node.out, [].concat(_toConsumableArray$2(nodeStack), [node]), currentDepth + (node.skip ? 0 : 1)); - } - }; - for (var i = 0, l = nodes.length; i < l; i++) { - if (_loop()) continue; - } - } - } - - // - - var DAG_LEVEL_NODE_RATIO = 2; - - // whenever styling props are changed that require a canvas redraw - var notifyRedraw = function notifyRedraw(_, state) { - return state.onNeedsRedraw && state.onNeedsRedraw(); - }; - var updDataPhotons = function updDataPhotons(_, state) { - if (!state.isShadow) { - // Add photon particles - var linkParticlesAccessor = index$2(state.linkDirectionalParticles); - state.graphData.links.forEach(function (link) { - var numPhotons = Math.round(Math.abs(linkParticlesAccessor(link))); - if (numPhotons) { - link.__photons = _toConsumableArray$2(Array(numPhotons)).map(function () { - return {}; - }); - } else { - delete link.__photons; - } - }); - } - }; - var CanvasForceGraph = index$3({ - props: { - graphData: { - "default": { - nodes: [], - links: [] - }, - onChange: function onChange(_, state) { - state.engineRunning = false; // Pause simulation - updDataPhotons(_, state); - } - }, - dagMode: { - onChange: function onChange(dagMode, state) { - // td, bu, lr, rl, radialin, radialout - !dagMode && (state.graphData.nodes || []).forEach(function (n) { - return n.fx = n.fy = undefined; - }); // unfix nodes when disabling dag mode - } - }, - - dagLevelDistance: {}, - dagNodeFilter: { - "default": function _default(node) { - return true; - } - }, - onDagError: { - triggerUpdate: false - }, - nodeRelSize: { - "default": 4, - triggerUpdate: false, - onChange: notifyRedraw - }, - // area per val unit - nodeId: { - "default": 'id' - }, - nodeVal: { - "default": 'val', - triggerUpdate: false, - onChange: notifyRedraw - }, - nodeColor: { - "default": 'color', - triggerUpdate: false, - onChange: notifyRedraw - }, - nodeAutoColorBy: {}, - nodeCanvasObject: { - triggerUpdate: false, - onChange: notifyRedraw - }, - nodeCanvasObjectMode: { - "default": function _default() { - return 'replace'; - }, - triggerUpdate: false, - onChange: notifyRedraw - }, - nodeVisibility: { - "default": true, - triggerUpdate: false, - onChange: notifyRedraw - }, - linkSource: { - "default": 'source' - }, - linkTarget: { - "default": 'target' - }, - linkVisibility: { - "default": true, - triggerUpdate: false, - onChange: notifyRedraw - }, - linkColor: { - "default": 'color', - triggerUpdate: false, - onChange: notifyRedraw - }, - linkAutoColorBy: {}, - linkLineDash: { - triggerUpdate: false, - onChange: notifyRedraw - }, - linkWidth: { - "default": 1, - triggerUpdate: false, - onChange: notifyRedraw - }, - linkCurvature: { - "default": 0, - triggerUpdate: false, - onChange: notifyRedraw - }, - linkCanvasObject: { - triggerUpdate: false, - onChange: notifyRedraw - }, - linkCanvasObjectMode: { - "default": function _default() { - return 'replace'; - }, - triggerUpdate: false, - onChange: notifyRedraw - }, - linkDirectionalArrowLength: { - "default": 0, - triggerUpdate: false, - onChange: notifyRedraw - }, - linkDirectionalArrowColor: { - triggerUpdate: false, - onChange: notifyRedraw - }, - linkDirectionalArrowRelPos: { - "default": 0.5, - triggerUpdate: false, - onChange: notifyRedraw - }, - // value between 0<>1 indicating the relative pos along the (exposed) line - linkDirectionalParticles: { - "default": 0, - triggerUpdate: false, - onChange: updDataPhotons - }, - // animate photons travelling in the link direction - linkDirectionalParticleSpeed: { - "default": 0.01, - triggerUpdate: false - }, - // in link length ratio per frame - linkDirectionalParticleWidth: { - "default": 4, - triggerUpdate: false - }, - linkDirectionalParticleColor: { - triggerUpdate: false - }, - globalScale: { - "default": 1, - triggerUpdate: false - }, - d3AlphaMin: { - "default": 0, - triggerUpdate: false - }, - d3AlphaDecay: { - "default": 0.0228, - triggerUpdate: false, - onChange: function onChange(alphaDecay, state) { - state.forceLayout.alphaDecay(alphaDecay); - } - }, - d3AlphaTarget: { - "default": 0, - triggerUpdate: false, - onChange: function onChange(alphaTarget, state) { - state.forceLayout.alphaTarget(alphaTarget); - } - }, - d3VelocityDecay: { - "default": 0.4, - triggerUpdate: false, - onChange: function onChange(velocityDecay, state) { - state.forceLayout.velocityDecay(velocityDecay); - } - }, - warmupTicks: { - "default": 0, - triggerUpdate: false - }, - // how many times to tick the force engine at init before starting to render - cooldownTicks: { - "default": Infinity, - triggerUpdate: false - }, - cooldownTime: { - "default": 15000, - triggerUpdate: false - }, - // ms - onUpdate: { - "default": function _default() {}, - triggerUpdate: false - }, - onFinishUpdate: { - "default": function _default() {}, - triggerUpdate: false - }, - onEngineTick: { - "default": function _default() {}, - triggerUpdate: false - }, - onEngineStop: { - "default": function _default() {}, - triggerUpdate: false - }, - onNeedsRedraw: { - triggerUpdate: false - }, - isShadow: { - "default": false, - triggerUpdate: false - } - }, - methods: { - // Expose d3 forces for external manipulation - d3Force: function d3Force(state, forceName, forceFn) { - if (forceFn === undefined) { - return state.forceLayout.force(forceName); // Force getter - } - - state.forceLayout.force(forceName, forceFn); // Force setter - return this; - }, - d3ReheatSimulation: function d3ReheatSimulation(state) { - state.forceLayout.alpha(1); - this.resetCountdown(); - return this; - }, - // reset cooldown state - resetCountdown: function resetCountdown(state) { - state.cntTicks = 0; - state.startTickTime = new Date(); - state.engineRunning = true; - return this; - }, - isEngineRunning: function isEngineRunning(state) { - return !!state.engineRunning; - }, - tickFrame: function tickFrame(state) { - !state.isShadow && layoutTick(); - paintLinks(); - !state.isShadow && paintArrows(); - !state.isShadow && paintPhotons(); - paintNodes(); - return this; - - // - - function layoutTick() { - if (state.engineRunning) { - if (++state.cntTicks > state.cooldownTicks || new Date() - state.startTickTime > state.cooldownTime || state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin) { - state.engineRunning = false; // Stop ticking graph - state.onEngineStop(); - } else { - state.forceLayout.tick(); // Tick it - state.onEngineTick(); - } - } - } - function paintNodes() { - var getVisibility = index$2(state.nodeVisibility); - var getVal = index$2(state.nodeVal); - var getColor = index$2(state.nodeColor); - var getNodeCanvasObjectMode = index$2(state.nodeCanvasObjectMode); - var ctx = state.ctx; - - // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing) - var padAmount = state.isShadow / state.globalScale; - var visibleNodes = state.graphData.nodes.filter(getVisibility); - ctx.save(); - visibleNodes.forEach(function (node) { - var nodeCanvasObjectMode = getNodeCanvasObjectMode(node); - if (state.nodeCanvasObject && (nodeCanvasObjectMode === 'before' || nodeCanvasObjectMode === 'replace')) { - // Custom node before/replace paint - state.nodeCanvasObject(node, ctx, state.globalScale); - if (nodeCanvasObjectMode === 'replace') { - ctx.restore(); - return; - } - } - - // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing) - var r = Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize + padAmount; - ctx.beginPath(); - ctx.arc(node.x, node.y, r, 0, 2 * Math.PI, false); - ctx.fillStyle = getColor(node) || 'rgba(31, 120, 180, 0.92)'; - ctx.fill(); - if (state.nodeCanvasObject && nodeCanvasObjectMode === 'after') { - // Custom node after paint - state.nodeCanvasObject(node, state.ctx, state.globalScale); - } - }); - ctx.restore(); - } - function paintLinks() { - var getVisibility = index$2(state.linkVisibility); - var getColor = index$2(state.linkColor); - var getWidth = index$2(state.linkWidth); - var getLineDash = index$2(state.linkLineDash); - var getCurvature = index$2(state.linkCurvature); - var getLinkCanvasObjectMode = index$2(state.linkCanvasObjectMode); - var ctx = state.ctx; - - // Draw wider lines by 2px on shadow canvas for more precise hovering (due to boundary anti-aliasing) - var padAmount = state.isShadow * 2; - var visibleLinks = state.graphData.links.filter(getVisibility); - visibleLinks.forEach(calcLinkControlPoints); // calculate curvature control points for all visible links - - var beforeCustomLinks = [], - afterCustomLinks = [], - defaultPaintLinks = visibleLinks; - if (state.linkCanvasObject) { - var replaceCustomLinks = [], - otherCustomLinks = []; - visibleLinks.forEach(function (d) { - return ({ - before: beforeCustomLinks, - after: afterCustomLinks, - replace: replaceCustomLinks - }[getLinkCanvasObjectMode(d)] || otherCustomLinks).push(d); - }); - defaultPaintLinks = [].concat(_toConsumableArray$2(beforeCustomLinks), afterCustomLinks, otherCustomLinks); - beforeCustomLinks = beforeCustomLinks.concat(replaceCustomLinks); - } - - // Custom link before paints - ctx.save(); - beforeCustomLinks.forEach(function (link) { - return state.linkCanvasObject(link, ctx, state.globalScale); - }); - ctx.restore(); - - // Bundle strokes per unique color/width/dash for performance optimization - var linksPerColor = index(defaultPaintLinks, [getColor, getWidth, getLineDash]); - ctx.save(); - Object.entries(linksPerColor).forEach(function (_ref) { - var _ref2 = _slicedToArray$2(_ref, 2), - color = _ref2[0], - linksPerWidth = _ref2[1]; - var lineColor = !color || color === 'undefined' ? 'rgba(0,0,0,0.15)' : color; - Object.entries(linksPerWidth).forEach(function (_ref3) { - var _ref4 = _slicedToArray$2(_ref3, 2), - width = _ref4[0], - linesPerLineDash = _ref4[1]; - var lineWidth = (width || 1) / state.globalScale + padAmount; - Object.entries(linesPerLineDash).forEach(function (_ref5) { - var _ref6 = _slicedToArray$2(_ref5, 2); - _ref6[0]; - var links = _ref6[1]; - var lineDashSegments = getLineDash(links[0]); - ctx.beginPath(); - links.forEach(function (link) { - var start = link.source; - var end = link.target; - if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link - - ctx.moveTo(start.x, start.y); - var controlPoints = link.__controlPoints; - if (!controlPoints) { - // Straight line - ctx.lineTo(end.x, end.y); - } else { - // Use quadratic curves for regular lines and bezier for loops - ctx[controlPoints.length === 2 ? 'quadraticCurveTo' : 'bezierCurveTo'].apply(ctx, _toConsumableArray$2(controlPoints).concat([end.x, end.y])); - } - }); - ctx.strokeStyle = lineColor; - ctx.lineWidth = lineWidth; - ctx.setLineDash(lineDashSegments || []); - ctx.stroke(); - }); - }); - }); - ctx.restore(); - - // Custom link after paints - ctx.save(); - afterCustomLinks.forEach(function (link) { - return state.linkCanvasObject(link, ctx, state.globalScale); - }); - ctx.restore(); - - // - - function calcLinkControlPoints(link) { - var curvature = getCurvature(link); - if (!curvature) { - // straight line - link.__controlPoints = null; - return; - } - var start = link.source; - var end = link.target; - if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link - - var l = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)); // line length - - if (l > 0) { - var a = Math.atan2(end.y - start.y, end.x - start.x); // line angle - var d = l * curvature; // control point distance - - var cp = { - // control point - x: (start.x + end.x) / 2 + d * Math.cos(a - Math.PI / 2), - y: (start.y + end.y) / 2 + d * Math.sin(a - Math.PI / 2) - }; - link.__controlPoints = [cp.x, cp.y]; - } else { - // Same point, draw a loop - var _d = curvature * 70; - link.__controlPoints = [end.x, end.y - _d, end.x + _d, end.y]; - } - } - } - function paintArrows() { - var ARROW_WH_RATIO = 1.6; - var ARROW_VLEN_RATIO = 0.2; - var getLength = index$2(state.linkDirectionalArrowLength); - var getRelPos = index$2(state.linkDirectionalArrowRelPos); - var getVisibility = index$2(state.linkVisibility); - var getColor = index$2(state.linkDirectionalArrowColor || state.linkColor); - var getNodeVal = index$2(state.nodeVal); - var ctx = state.ctx; - ctx.save(); - state.graphData.links.filter(getVisibility).forEach(function (link) { - var arrowLength = getLength(link); - if (!arrowLength || arrowLength < 0) return; - var start = link.source; - var end = link.target; - if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link - - var startR = Math.sqrt(Math.max(0, getNodeVal(start) || 1)) * state.nodeRelSize; - var endR = Math.sqrt(Math.max(0, getNodeVal(end) || 1)) * state.nodeRelSize; - var arrowRelPos = Math.min(1, Math.max(0, getRelPos(link))); - var arrowColor = getColor(link) || 'rgba(0,0,0,0.28)'; - var arrowHalfWidth = arrowLength / ARROW_WH_RATIO / 2; - - // Construct bezier for curved lines - var bzLine = link.__controlPoints && _construct(Bezier, [start.x, start.y].concat(_toConsumableArray$2(link.__controlPoints), [end.x, end.y])); - var getCoordsAlongLine = bzLine ? function (t) { - return bzLine.get(t); - } // get position along bezier line - : function (t) { - return { - // straight line: interpolate linearly - x: start.x + (end.x - start.x) * t || 0, - y: start.y + (end.y - start.y) * t || 0 - }; - }; - var lineLen = bzLine ? bzLine.length() : Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)); - var posAlongLine = startR + arrowLength + (lineLen - startR - endR - arrowLength) * arrowRelPos; - var arrowHead = getCoordsAlongLine(posAlongLine / lineLen); - var arrowTail = getCoordsAlongLine((posAlongLine - arrowLength) / lineLen); - var arrowTailVertex = getCoordsAlongLine((posAlongLine - arrowLength * (1 - ARROW_VLEN_RATIO)) / lineLen); - var arrowTailAngle = Math.atan2(arrowHead.y - arrowTail.y, arrowHead.x - arrowTail.x) - Math.PI / 2; - ctx.beginPath(); - ctx.moveTo(arrowHead.x, arrowHead.y); - ctx.lineTo(arrowTail.x + arrowHalfWidth * Math.cos(arrowTailAngle), arrowTail.y + arrowHalfWidth * Math.sin(arrowTailAngle)); - ctx.lineTo(arrowTailVertex.x, arrowTailVertex.y); - ctx.lineTo(arrowTail.x - arrowHalfWidth * Math.cos(arrowTailAngle), arrowTail.y - arrowHalfWidth * Math.sin(arrowTailAngle)); - ctx.fillStyle = arrowColor; - ctx.fill(); - }); - ctx.restore(); - } - function paintPhotons() { - var getNumPhotons = index$2(state.linkDirectionalParticles); - var getSpeed = index$2(state.linkDirectionalParticleSpeed); - var getDiameter = index$2(state.linkDirectionalParticleWidth); - var getVisibility = index$2(state.linkVisibility); - var getColor = index$2(state.linkDirectionalParticleColor || state.linkColor); - var ctx = state.ctx; - ctx.save(); - state.graphData.links.filter(getVisibility).forEach(function (link) { - var numCyclePhotons = getNumPhotons(link); - if (!link.hasOwnProperty('__photons') || !link.__photons.length) return; - var start = link.source; - var end = link.target; - if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link - - var particleSpeed = getSpeed(link); - var photons = link.__photons || []; - var photonR = Math.max(0, getDiameter(link) / 2) / Math.sqrt(state.globalScale); - var photonColor = getColor(link) || 'rgba(0,0,0,0.28)'; - ctx.fillStyle = photonColor; - - // Construct bezier for curved lines - var bzLine = link.__controlPoints ? _construct(Bezier, [start.x, start.y].concat(_toConsumableArray$2(link.__controlPoints), [end.x, end.y])) : null; - var cyclePhotonIdx = 0; - var needsCleanup = false; // whether some photons need to be removed from list - photons.forEach(function (photon) { - var singleHop = !!photon.__singleHop; - if (!photon.hasOwnProperty('__progressRatio')) { - photon.__progressRatio = singleHop ? 0 : cyclePhotonIdx / numCyclePhotons; - } - !singleHop && cyclePhotonIdx++; // increase regular photon index - - photon.__progressRatio += particleSpeed; - if (photon.__progressRatio >= 1) { - if (!singleHop) { - photon.__progressRatio = photon.__progressRatio % 1; - } else { - needsCleanup = true; - return; - } - } - var photonPosRatio = photon.__progressRatio; - var coords = bzLine ? bzLine.get(photonPosRatio) // get position along bezier line - : { - // straight line: interpolate linearly - x: start.x + (end.x - start.x) * photonPosRatio || 0, - y: start.y + (end.y - start.y) * photonPosRatio || 0 - }; - ctx.beginPath(); - ctx.arc(coords.x, coords.y, photonR, 0, 2 * Math.PI, false); - ctx.fill(); - }); - if (needsCleanup) { - // remove expired single hop photons - link.__photons = link.__photons.filter(function (photon) { - return !photon.__singleHop || photon.__progressRatio <= 1; - }); - } - }); - ctx.restore(); - } - }, - emitParticle: function emitParticle(state, link) { - if (link) { - !link.__photons && (link.__photons = []); - link.__photons.push({ - __singleHop: true - }); // add a single hop particle - } - - return this; - } - }, - stateInit: function stateInit() { - return { - forceLayout: d3ForceSimulation().force('link', d3ForceLink()).force('charge', d3ForceManyBody()).force('center', d3ForceCenter()).force('dagRadial', null).stop(), - engineRunning: false - }; - }, - init: function init(canvasCtx, state) { - // Main canvas object to manipulate - state.ctx = canvasCtx; - }, - update: function update(state) { - state.engineRunning = false; // Pause simulation - state.onUpdate(); - if (state.nodeAutoColorBy !== null) { - // Auto add color to uncolored nodes - autoColorObjects(state.graphData.nodes, index$2(state.nodeAutoColorBy), state.nodeColor); - } - if (state.linkAutoColorBy !== null) { - // Auto add color to uncolored links - autoColorObjects(state.graphData.links, index$2(state.linkAutoColorBy), state.linkColor); - } - - // parse links - state.graphData.links.forEach(function (link) { - link.source = link[state.linkSource]; - link.target = link[state.linkTarget]; - }); - - // Feed data to force-directed layout - state.forceLayout.stop().alpha(1) // re-heat the simulation - .nodes(state.graphData.nodes); - - // add links (if link force is still active) - var linkForce = state.forceLayout.force('link'); - if (linkForce) { - linkForce.id(function (d) { - return d[state.nodeId]; - }).links(state.graphData.links); - } - - // setup dag force constraints - var nodeDepths = state.dagMode && getDagDepths(state.graphData, function (node) { - return node[state.nodeId]; - }, { - nodeFilter: state.dagNodeFilter, - onLoopError: state.onDagError || undefined - }); - var maxDepth = Math.max.apply(Math, _toConsumableArray$2(Object.values(nodeDepths || []))); - var dagLevelDistance = state.dagLevelDistance || state.graphData.nodes.length / (maxDepth || 1) * DAG_LEVEL_NODE_RATIO * (['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? 0.7 : 1); - - // Fix nodes to x,y for dag mode - if (state.dagMode) { - var getFFn = function getFFn(fix, invert) { - return function (node) { - return !fix ? undefined : (nodeDepths[node[state.nodeId]] - maxDepth / 2) * dagLevelDistance * (invert ? -1 : 1); - }; - }; - var fxFn = getFFn(['lr', 'rl'].indexOf(state.dagMode) !== -1, state.dagMode === 'rl'); - var fyFn = getFFn(['td', 'bu'].indexOf(state.dagMode) !== -1, state.dagMode === 'bu'); - state.graphData.nodes.filter(state.dagNodeFilter).forEach(function (node) { - node.fx = fxFn(node); - node.fy = fyFn(node); - }); - } - - // Use radial force for radial dags - state.forceLayout.force('dagRadial', ['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? d3ForceRadial(function (node) { - var nodeDepth = nodeDepths[node[state.nodeId]] || -1; - return (state.dagMode === 'radialin' ? maxDepth - nodeDepth : nodeDepth) * dagLevelDistance; - }).strength(function (node) { - return state.dagNodeFilter(node) ? 1 : 0; - }) : null); - for (var i = 0; i < state.warmupTicks && !(state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin); i++) { - state.forceLayout.tick(); - } // Initial ticks before starting to render - - this.resetCountdown(); - state.onFinishUpdate(); - } - }); - - function linkKapsule (kapsulePropNames, kapsuleType) { - var propNames = kapsulePropNames instanceof Array ? kapsulePropNames : [kapsulePropNames]; - var dummyK = new kapsuleType(); // To extract defaults - dummyK._destructor && dummyK._destructor(); - return { - linkProp: function linkProp(prop) { - // link property config - return { - "default": dummyK[prop](), - onChange: function onChange(v, state) { - propNames.forEach(function (propName) { - return state[propName][prop](v); - }); - }, - triggerUpdate: false - }; - }, - linkMethod: function linkMethod(method) { - // link method pass-through - return function (state) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - var returnVals = []; - propNames.forEach(function (propName) { - var kapsuleInstance = state[propName]; - var returnVal = kapsuleInstance[method].apply(kapsuleInstance, args); - if (returnVal !== kapsuleInstance) { - returnVals.push(returnVal); - } - }); - return returnVals.length ? returnVals[0] : this; // chain based on the parent object, not the inner kapsule - }; - } - }; - } - - var HOVER_CANVAS_THROTTLE_DELAY = 800; // ms to throttle shadow canvas updates for perf improvement - var ZOOM2NODES_FACTOR = 4; - - // Expose config from forceGraph - var bindFG = linkKapsule('forceGraph', CanvasForceGraph); - var bindBoth = linkKapsule(['forceGraph', 'shadowGraph'], CanvasForceGraph); - var linkedProps = Object.assign.apply(Object, _toConsumableArray$2(['nodeColor', 'nodeAutoColorBy', 'nodeCanvasObject', 'nodeCanvasObjectMode', 'linkColor', 'linkAutoColorBy', 'linkLineDash', 'linkWidth', 'linkCanvasObject', 'linkCanvasObjectMode', 'linkDirectionalArrowLength', 'linkDirectionalArrowColor', 'linkDirectionalArrowRelPos', 'linkDirectionalParticles', 'linkDirectionalParticleSpeed', 'linkDirectionalParticleWidth', 'linkDirectionalParticleColor', 'dagMode', 'dagLevelDistance', 'dagNodeFilter', 'onDagError', 'd3AlphaMin', 'd3AlphaDecay', 'd3VelocityDecay', 'warmupTicks', 'cooldownTicks', 'cooldownTime', 'onEngineTick', 'onEngineStop'].map(function (p) { - return _defineProperty({}, p, bindFG.linkProp(p)); - })).concat(_toConsumableArray$2(['nodeRelSize', 'nodeId', 'nodeVal', 'nodeVisibility', 'linkSource', 'linkTarget', 'linkVisibility', 'linkCurvature'].map(function (p) { - return _defineProperty({}, p, bindBoth.linkProp(p)); - })))); - var linkedMethods = Object.assign.apply(Object, _toConsumableArray$2(['d3Force', 'd3ReheatSimulation', 'emitParticle'].map(function (p) { - return _defineProperty({}, p, bindFG.linkMethod(p)); - }))); - function adjustCanvasSize(state) { - if (state.canvas) { - var curWidth = state.canvas.width; - var curHeight = state.canvas.height; - if (curWidth === 300 && curHeight === 150) { - // Default canvas dimensions - curWidth = curHeight = 0; - } - var pxScale = window.devicePixelRatio; // 2 on retina displays - curWidth /= pxScale; - curHeight /= pxScale; - - // Resize canvases - [state.canvas, state.shadowCanvas].forEach(function (canvas) { - // Element size - canvas.style.width = "".concat(state.width, "px"); - canvas.style.height = "".concat(state.height, "px"); - - // Memory size (scaled to avoid blurriness) - canvas.width = state.width * pxScale; - canvas.height = state.height * pxScale; - - // Normalize coordinate system to use css pixels (on init only) - if (!curWidth && !curHeight) { - canvas.getContext('2d').scale(pxScale, pxScale); - } - }); - - // Relative center panning based on 0,0 - var k = transform(state.canvas).k; - state.zoom.translateBy(state.zoom.__baseElem, (state.width - curWidth) / 2 / k, (state.height - curHeight) / 2 / k); - state.needsRedraw = true; - } - } - function resetTransform(ctx) { - var pxRatio = window.devicePixelRatio; - ctx.setTransform(pxRatio, 0, 0, pxRatio, 0, 0); - } - function clearCanvas(ctx, width, height) { - ctx.save(); - resetTransform(ctx); // reset transform - ctx.clearRect(0, 0, width, height); - ctx.restore(); //restore transforms - } - - // - - var forceGraph = index$3({ - props: _objectSpread2({ - width: { - "default": window.innerWidth, - onChange: function onChange(_, state) { - return adjustCanvasSize(state); - }, - triggerUpdate: false - }, - height: { - "default": window.innerHeight, - onChange: function onChange(_, state) { - return adjustCanvasSize(state); - }, - triggerUpdate: false - }, - graphData: { - "default": { - nodes: [], - links: [] - }, - onChange: function onChange(d, state) { - [{ - type: 'Node', - objs: d.nodes - }, { - type: 'Link', - objs: d.links - }].forEach(hexIndex); - state.forceGraph.graphData(d); - state.shadowGraph.graphData(d); - function hexIndex(_ref4) { - var type = _ref4.type, - objs = _ref4.objs; - objs.filter(function (d) { - if (!d.hasOwnProperty('__indexColor')) return true; - var cur = state.colorTracker.lookup(d.__indexColor); - return !cur || !cur.hasOwnProperty('d') || cur.d !== d; - }).forEach(function (d) { - // store object lookup color - d.__indexColor = state.colorTracker.register({ - type: type, - d: d - }); - }); - } - }, - triggerUpdate: false - }, - backgroundColor: { - onChange: function onChange(color, state) { - state.canvas && color && (state.canvas.style.background = color); - }, - triggerUpdate: false - }, - nodeLabel: { - "default": 'name', - triggerUpdate: false - }, - nodePointerAreaPaint: { - onChange: function onChange(paintFn, state) { - state.shadowGraph.nodeCanvasObject(!paintFn ? null : function (node, ctx, globalScale) { - return paintFn(node, node.__indexColor, ctx, globalScale); - }); - state.flushShadowCanvas && state.flushShadowCanvas(); - }, - triggerUpdate: false - }, - linkPointerAreaPaint: { - onChange: function onChange(paintFn, state) { - state.shadowGraph.linkCanvasObject(!paintFn ? null : function (link, ctx, globalScale) { - return paintFn(link, link.__indexColor, ctx, globalScale); - }); - state.flushShadowCanvas && state.flushShadowCanvas(); - }, - triggerUpdate: false - }, - linkLabel: { - "default": 'name', - triggerUpdate: false - }, - linkHoverPrecision: { - "default": 4, - triggerUpdate: false - }, - minZoom: { - "default": 0.01, - onChange: function onChange(minZoom, state) { - state.zoom.scaleExtent([minZoom, state.zoom.scaleExtent()[1]]); - }, - triggerUpdate: false - }, - maxZoom: { - "default": 1000, - onChange: function onChange(maxZoom, state) { - state.zoom.scaleExtent([state.zoom.scaleExtent()[0], maxZoom]); - }, - triggerUpdate: false - }, - enableNodeDrag: { - "default": true, - triggerUpdate: false - }, - enableZoomInteraction: { - "default": true, - triggerUpdate: false - }, - enablePanInteraction: { - "default": true, - triggerUpdate: false - }, - enableZoomPanInteraction: { - "default": true, - triggerUpdate: false - }, - // to be deprecated - enablePointerInteraction: { - "default": true, - onChange: function onChange(_, state) { - state.hoverObj = null; - }, - triggerUpdate: false - }, - autoPauseRedraw: { - "default": true, - triggerUpdate: false - }, - onNodeDrag: { - "default": function _default() {}, - triggerUpdate: false - }, - onNodeDragEnd: { - "default": function _default() {}, - triggerUpdate: false - }, - onNodeClick: { - triggerUpdate: false - }, - onNodeRightClick: { - triggerUpdate: false - }, - onNodeHover: { - triggerUpdate: false - }, - onLinkClick: { - triggerUpdate: false - }, - onLinkRightClick: { - triggerUpdate: false - }, - onLinkHover: { - triggerUpdate: false - }, - onBackgroundClick: { - triggerUpdate: false - }, - onBackgroundRightClick: { - triggerUpdate: false - }, - onZoom: { - triggerUpdate: false - }, - onZoomEnd: { - triggerUpdate: false - }, - onRenderFramePre: { - triggerUpdate: false - }, - onRenderFramePost: { - triggerUpdate: false - } - }, linkedProps), - aliases: { - // Prop names supported for backwards compatibility - stopAnimation: 'pauseAnimation' - }, - methods: _objectSpread2({ - graph2ScreenCoords: function graph2ScreenCoords(state, x, y) { - var t = transform(state.canvas); - return { - x: x * t.k + t.x, - y: y * t.k + t.y - }; - }, - screen2GraphCoords: function screen2GraphCoords(state, x, y) { - var t = transform(state.canvas); - return { - x: (x - t.x) / t.k, - y: (y - t.y) / t.k - }; - }, - centerAt: function centerAt(state, x, y, transitionDuration) { - if (!state.canvas) return null; // no canvas yet - - // setter - if (x !== undefined || y !== undefined) { - var finalPos = Object.assign({}, x !== undefined ? { - x: x - } : {}, y !== undefined ? { - y: y - } : {}); - if (!transitionDuration) { - // no animation - setCenter(finalPos); - } else { - new Tween(getCenter()).to(finalPos, transitionDuration).easing(Easing.Quadratic.Out).onUpdate(setCenter).start(); - } - return this; - } - - // getter - return getCenter(); - - // - - function getCenter() { - var t = transform(state.canvas); - return { - x: (state.width / 2 - t.x) / t.k, - y: (state.height / 2 - t.y) / t.k - }; - } - function setCenter(_ref5) { - var x = _ref5.x, - y = _ref5.y; - state.zoom.translateTo(state.zoom.__baseElem, x === undefined ? getCenter().x : x, y === undefined ? getCenter().y : y); - state.needsRedraw = true; - } - }, - zoom: function zoom(state, k, transitionDuration) { - if (!state.canvas) return null; // no canvas yet - - // setter - if (k !== undefined) { - if (!transitionDuration) { - // no animation - setZoom(k); - } else { - new Tween({ - k: getZoom() - }).to({ - k: k - }, transitionDuration).easing(Easing.Quadratic.Out).onUpdate(function (_ref6) { - var k = _ref6.k; - return setZoom(k); - }).start(); - } - return this; - } - - // getter - return getZoom(); - - // - - function getZoom() { - return transform(state.canvas).k; - } - function setZoom(k) { - state.zoom.scaleTo(state.zoom.__baseElem, k); - state.needsRedraw = true; - } - }, - zoomToFit: function zoomToFit(state) { - var transitionDuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var padding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; - for (var _len = arguments.length, bboxArgs = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { - bboxArgs[_key - 3] = arguments[_key]; - } - var bbox = this.getGraphBbox.apply(this, bboxArgs); - if (bbox) { - var center = { - x: (bbox.x[0] + bbox.x[1]) / 2, - y: (bbox.y[0] + bbox.y[1]) / 2 - }; - var zoomK = Math.max(1e-12, Math.min(1e12, (state.width - padding * 2) / (bbox.x[1] - bbox.x[0]), (state.height - padding * 2) / (bbox.y[1] - bbox.y[0]))); - this.centerAt(center.x, center.y, transitionDuration); - this.zoom(zoomK, transitionDuration); - } - return this; - }, - getGraphBbox: function getGraphBbox(state) { - var nodeFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () { - return true; - }; - var getVal = index$2(state.nodeVal); - var getR = function getR(node) { - return Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize; - }; - var nodesPos = state.graphData.nodes.filter(nodeFilter).map(function (node) { - return { - x: node.x, - y: node.y, - r: getR(node) - }; - }); - return !nodesPos.length ? null : { - x: [min$1(nodesPos, function (node) { - return node.x - node.r; - }), max$1(nodesPos, function (node) { - return node.x + node.r; - })], - y: [min$1(nodesPos, function (node) { - return node.y - node.r; - }), max$1(nodesPos, function (node) { - return node.y + node.r; - })] - }; - }, - pauseAnimation: function pauseAnimation(state) { - if (state.animationFrameRequestId) { - cancelAnimationFrame(state.animationFrameRequestId); - state.animationFrameRequestId = null; - } - return this; - }, - resumeAnimation: function resumeAnimation(state) { - if (!state.animationFrameRequestId) { - this._animationCycle(); - } - return this; - }, - _destructor: function _destructor() { - this.pauseAnimation(); - this.graphData({ - nodes: [], - links: [] - }); - } - }, linkedMethods), - stateInit: function stateInit() { - return { - lastSetZoom: 1, - zoom: d3Zoom(), - forceGraph: new CanvasForceGraph(), - shadowGraph: new CanvasForceGraph().cooldownTicks(0).nodeColor('__indexColor').linkColor('__indexColor').isShadow(true), - colorTracker: new _default() // indexed objects for rgb lookup - }; - }, - - init: function init(domNode, state) { - var _this = this; - // Wipe DOM - domNode.innerHTML = ''; - - // Container anchor for canvas and tooltip - var container = document.createElement('div'); - container.classList.add('force-graph-container'); - container.style.position = 'relative'; - domNode.appendChild(container); - state.canvas = document.createElement('canvas'); - if (state.backgroundColor) state.canvas.style.background = state.backgroundColor; - container.appendChild(state.canvas); - state.shadowCanvas = document.createElement('canvas'); - - // Show shadow canvas - //state.shadowCanvas.style.position = 'absolute'; - //state.shadowCanvas.style.top = '0'; - //state.shadowCanvas.style.left = '0'; - //container.appendChild(state.shadowCanvas); - - var ctx = state.canvas.getContext('2d'); - var shadowCtx = state.shadowCanvas.getContext('2d', { - willReadFrequently: true - }); - var pointerPos = { - x: -1e12, - y: -1e12 - }; - var getObjUnderPointer = function getObjUnderPointer() { - var obj = null; - var pxScale = window.devicePixelRatio; - var px = pointerPos.x > 0 && pointerPos.y > 0 ? shadowCtx.getImageData(pointerPos.x * pxScale, pointerPos.y * pxScale, 1, 1) : null; - // Lookup object per pixel color - px && (obj = state.colorTracker.lookup(px.data)); - return obj; - }; - - // Setup node drag interaction - d3Select(state.canvas).call(d3Drag().subject(function () { - if (!state.enableNodeDrag) { - return null; - } - var obj = getObjUnderPointer(); - return obj && obj.type === 'Node' ? obj.d : null; // Only drag nodes - }).on('start', function (ev) { - var obj = ev.subject; - obj.__initialDragPos = { - x: obj.x, - y: obj.y, - fx: obj.fx, - fy: obj.fy - }; - - // keep engine running at low intensity throughout drag - if (!ev.active) { - obj.fx = obj.x; - obj.fy = obj.y; // Fix points - } - - // drag cursor - state.canvas.classList.add('grabbable'); - }).on('drag', function (ev) { - var obj = ev.subject; - var initPos = obj.__initialDragPos; - var dragPos = ev; - var k = transform(state.canvas).k; - var translate = { - x: initPos.x + (dragPos.x - initPos.x) / k - obj.x, - y: initPos.y + (dragPos.y - initPos.y) / k - obj.y - }; - - // Move fx/fy (and x/y) of nodes based on the scaled drag distance since the drag start - ['x', 'y'].forEach(function (c) { - return obj["f".concat(c)] = obj[c] = initPos[c] + (dragPos[c] - initPos[c]) / k; - }); - - // prevent freeze while dragging - state.forceGraph.d3AlphaTarget(0.3) // keep engine running at low intensity throughout drag - .resetCountdown(); // prevent freeze while dragging - - state.isPointerDragging = true; - obj.__dragged = true; - state.onNodeDrag(obj, translate); - }).on('end', function (ev) { - var obj = ev.subject; - var initPos = obj.__initialDragPos; - var translate = { - x: obj.x - initPos.x, - y: obj.y - initPos.y - }; - if (initPos.fx === undefined) { - obj.fx = undefined; - } - if (initPos.fy === undefined) { - obj.fy = undefined; - } - delete obj.__initialDragPos; - if (state.forceGraph.d3AlphaTarget()) { - state.forceGraph.d3AlphaTarget(0) // release engine low intensity - .resetCountdown(); // let the engine readjust after releasing fixed nodes - } - - // drag cursor - state.canvas.classList.remove('grabbable'); - state.isPointerDragging = false; - if (obj.__dragged) { - delete obj.__dragged; - state.onNodeDragEnd(obj, translate); - } - })); - - // Setup zoom / pan interaction - state.zoom(state.zoom.__baseElem = d3Select(state.canvas)); // Attach controlling elem for easy access - - state.zoom.__baseElem.on('dblclick.zoom', null); // Disable double-click to zoom - - state.zoom.filter(function (ev) { - return ( - // disable zoom interaction - !ev.button && state.enableZoomPanInteraction && (state.enableZoomInteraction || ev.type !== 'wheel') && (state.enablePanInteraction || ev.type === 'wheel') - ); - }).on('zoom', function (ev) { - var t = ev.transform; - [ctx, shadowCtx].forEach(function (c) { - resetTransform(c); - c.translate(t.x, t.y); - c.scale(t.k, t.k); - }); - state.onZoom && state.onZoom(_objectSpread2(_objectSpread2({}, t), _this.centerAt())); // report x,y coordinates relative to canvas center - state.needsRedraw = true; - }).on('end', function (ev) { - return state.onZoomEnd && state.onZoomEnd(_objectSpread2(_objectSpread2({}, ev.transform), _this.centerAt())); - }); - adjustCanvasSize(state); - state.forceGraph.onNeedsRedraw(function () { - return state.needsRedraw = true; - }).onFinishUpdate(function () { - // re-zoom, if still in default position (not user modified) - if (transform(state.canvas).k === state.lastSetZoom && state.graphData.nodes.length) { - state.zoom.scaleTo(state.zoom.__baseElem, state.lastSetZoom = ZOOM2NODES_FACTOR / Math.cbrt(state.graphData.nodes.length)); - state.needsRedraw = true; - } - }); - - // Setup tooltip - var toolTipElem = document.createElement('div'); - toolTipElem.classList.add('graph-tooltip'); - container.appendChild(toolTipElem); - - // Capture pointer coords on move or touchstart - ['pointermove', 'pointerdown'].forEach(function (evType) { - return container.addEventListener(evType, function (ev) { - if (evType === 'pointerdown') { - state.isPointerPressed = true; // track click state - state.pointerDownEvent = ev; - } - - // detect pointer drag on canvas pan - !state.isPointerDragging && ev.type === 'pointermove' && state.onBackgroundClick // only bother detecting drags this way if background clicks are enabled (so they don't trigger accidentally on canvas panning) - && (ev.pressure > 0 || state.isPointerPressed) // ev.pressure always 0 on Safari, so we use the isPointerPressed tracker - && (ev.pointerType !== 'touch' || ev.movementX === undefined || [ev.movementX, ev.movementY].some(function (m) { - return Math.abs(m) > 1; - })) // relax drag trigger sensitivity on touch events - && (state.isPointerDragging = true); - - // update the pointer pos - var offset = getOffset(container); - pointerPos.x = ev.pageX - offset.left; - pointerPos.y = ev.pageY - offset.top; - - // Move tooltip - toolTipElem.style.top = "".concat(pointerPos.y, "px"); - toolTipElem.style.left = "".concat(pointerPos.x, "px"); - - // adjust horizontal position to not exceed canvas boundaries - toolTipElem.style.transform = "translate(-".concat(pointerPos.x / state.width * 100, "%, ").concat( - // flip to above if near bottom - state.height - pointerPos.y < 100 ? 'calc(-100% - 8px)' : '21px', ")"); - - // - - function getOffset(el) { - var rect = el.getBoundingClientRect(), - scrollLeft = window.pageXOffset || document.documentElement.scrollLeft, - scrollTop = window.pageYOffset || document.documentElement.scrollTop; - return { - top: rect.top + scrollTop, - left: rect.left + scrollLeft - }; - } - }, { - passive: true - }); - }); - - // Handle click/touch events on nodes/links - container.addEventListener('pointerup', function (ev) { - state.isPointerPressed = false; - if (state.isPointerDragging) { - state.isPointerDragging = false; - return; // don't trigger click events after pointer drag (pan / node drag functionality) - } - - var cbEvents = [ev, state.pointerDownEvent]; - requestAnimationFrame(function () { - // trigger click events asynchronously, to allow hoverObj to be set (on frame) - if (ev.button === 0) { - // mouse left-click or touch - if (state.hoverObj) { - var fn = state["on".concat(state.hoverObj.type, "Click")]; - fn && fn.apply(void 0, [state.hoverObj.d].concat(cbEvents)); - } else { - state.onBackgroundClick && state.onBackgroundClick.apply(state, cbEvents); - } - } - if (ev.button === 2) { - // mouse right-click - if (state.hoverObj) { - var _fn = state["on".concat(state.hoverObj.type, "RightClick")]; - _fn && _fn.apply(void 0, [state.hoverObj.d].concat(cbEvents)); - } else { - state.onBackgroundRightClick && state.onBackgroundRightClick.apply(state, cbEvents); - } - } - }); - }, { - passive: true - }); - container.addEventListener('contextmenu', function (ev) { - if (!state.onBackgroundRightClick && !state.onNodeRightClick && !state.onLinkRightClick) return true; // default contextmenu behavior - ev.preventDefault(); - return false; - }); - state.forceGraph(ctx); - state.shadowGraph(shadowCtx); - - // - - var refreshShadowCanvas = throttle(function () { - // wipe canvas - clearCanvas(shadowCtx, state.width, state.height); - - // Adjust link hover area - state.shadowGraph.linkWidth(function (l) { - return index$2(state.linkWidth)(l) + state.linkHoverPrecision; - }); - - // redraw - var t = transform(state.canvas); - state.shadowGraph.globalScale(t.k).tickFrame(); - }, HOVER_CANVAS_THROTTLE_DELAY); - state.flushShadowCanvas = refreshShadowCanvas.flush; // hook to immediately invoke shadow canvas paint - - // Kick-off renderer - (this._animationCycle = function animate() { - // IIFE - var doRedraw = !state.autoPauseRedraw || !!state.needsRedraw || state.forceGraph.isEngineRunning() || state.graphData.links.some(function (d) { - return d.__photons && d.__photons.length; - }); - state.needsRedraw = false; - if (state.enablePointerInteraction) { - // Update tooltip and trigger onHover events - var obj = !state.isPointerDragging ? getObjUnderPointer() : null; // don't hover during drag - if (obj !== state.hoverObj) { - var prevObj = state.hoverObj; - var prevObjType = prevObj ? prevObj.type : null; - var objType = obj ? obj.type : null; - if (prevObjType && prevObjType !== objType) { - // Hover out - var fn = state["on".concat(prevObjType, "Hover")]; - fn && fn(null, prevObj.d); - } - if (objType) { - // Hover in - var _fn2 = state["on".concat(objType, "Hover")]; - _fn2 && _fn2(obj.d, prevObjType === objType ? prevObj.d : null); - } - var tooltipContent = obj ? index$2(state["".concat(obj.type.toLowerCase(), "Label")])(obj.d) || '' : ''; - toolTipElem.style.visibility = tooltipContent ? 'visible' : 'hidden'; - toolTipElem.innerHTML = tooltipContent; - - // set pointer if hovered object is clickable - state.canvas.classList[obj && state["on".concat(objType, "Click")] || !obj && state.onBackgroundClick ? 'add' : 'remove']('clickable'); - state.hoverObj = obj; - } - doRedraw && refreshShadowCanvas(); - } - if (doRedraw) { - // Wipe canvas - clearCanvas(ctx, state.width, state.height); - - // Frame cycle - var globalScale = transform(state.canvas).k; - state.onRenderFramePre && state.onRenderFramePre(ctx, globalScale); - state.forceGraph.globalScale(globalScale).tickFrame(); - state.onRenderFramePost && state.onRenderFramePost(ctx, globalScale); - } - update(); // update canvas animation tweens - - state.animationFrameRequestId = requestAnimationFrame(animate); - })(); - }, - update: function updateFn(state) {} - }); - - return forceGraph; - -})); -//# sourceMappingURL=force-graph.js.map diff --git a/hal-core/resources/web/js/lib/force-graph.min.js b/hal-core/resources/web/js/lib/force-graph.min.js deleted file mode 100644 index 42b88f34..00000000 --- a/hal-core/resources/web/js/lib/force-graph.min.js +++ /dev/null @@ -1,5 +0,0 @@ -// Version 1.43.4 force-graph - https://github.com/vasturiano/force-graph -!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t="undefined"!=typeof globalThis?globalThis:t||self).ForceGraph=n()}(this,(function(){"use strict";function n(t,n){var e=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(t,n).enumerable}))),e.push.apply(e,r)}return e}function e(t){for(var e=1;et.length)&&(n=t.length);for(var e=0,r=new Array(n);e=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),f.hasOwnProperty(n)?{space:f[n],local:t}:t}function p(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===h&&n.documentElement.namespaceURI===h?n.createElement(t):n.createElementNS(e,t)}}function g(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function y(t){var n=d(t);return(n.local?g:p)(n)}function v(){}function _(t){return null==t?v:function(){return this.querySelector(t)}}function m(){return[]}function x(t){return null==t?m:function(){return this.querySelectorAll(t)}}function b(t){return function(){return function(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}(t.apply(this,arguments))}}function w(t){return function(){return this.matches(t)}}function k(t){return function(n){return n.matches(t)}}var M=Array.prototype.find;function z(){return this.firstElementChild}var A=Array.prototype.filter;function S(){return Array.from(this.children)}function C(t){return new Array(t.length)}function E(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function O(t,n,e,r,i,o){for(var a,u=0,s=n.length,l=o.length;un?1:t>=n?0:NaN}function R(t){return function(){this.removeAttribute(t)}}function D(t){return function(){this.removeAttributeNS(t.space,t.local)}}function I(t,n){return function(){this.setAttribute(t,n)}}function U(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function F(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function L(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function q(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function B(t){return function(){this.style.removeProperty(t)}}function $(t,n,e){return function(){this.style.setProperty(t,n,e)}}function H(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function V(t,n){return t.style.getPropertyValue(n)||q(t).getComputedStyle(t,null).getPropertyValue(n)}function X(t){return function(){delete this[t]}}function G(t,n){return function(){this[t]=n}}function Y(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function W(t){return t.trim().split(/^|\s+/)}function Z(t){return t.classList||new Q(t)}function Q(t){this._node=t,this._names=W(t.getAttribute("class")||"")}function K(t,n){for(var e=Z(t),r=-1,i=n.length;++r=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var xt=[null];function bt(t,n){this._groups=t,this._parents=n}function wt(){return new bt([[document.documentElement]],xt)}function kt(t){return"string"==typeof t?new bt([[document.querySelector(t)]],[document.documentElement]):new bt([[t]],xt)}function Mt(t,n){if(t=function(t){let n;for(;n=t.sourceEvent;)t=n;return t}(t),void 0===n&&(n=t.currentTarget),n){var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();return r.x=t.clientX,r.y=t.clientY,[(r=r.matrixTransform(n.getScreenCTM().inverse())).x,r.y]}if(n.getBoundingClientRect){var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}}return[t.pageX,t.pageY]}bt.prototype=wt.prototype={constructor:bt,select:function(t){"function"!=typeof t&&(t=_(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i=x&&(x=m+1);!(_=y[x])&&++x=0;)(r=i[o])&&(a&&4^r.compareDocumentPosition(a)&&a.parentNode.insertBefore(r,a),a=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=T);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o1?this.each((null==n?B:"function"==typeof n?H:$)(t,n,null==e?"":e)):V(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?X:"function"==typeof n?Y:G)(t,n)):this.node()[t]},classed:function(t,n){var e=W(t+"");if(arguments.length<2){for(var r=Z(this.node()),i=-1,o=e.length;++i=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}}))}(t+""),a=o.length;if(!(arguments.length<2)){for(u=n?yt:gt,r=0;r{}};function At(){for(var t,n=0,e=arguments.length,r={};n=0&&(n=t.slice(e+1),t=t.slice(0,e)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))),a=-1,u=o.length;if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++a0)for(var e,r,i=new Array(e),o=0;o()=>t;function It(t,{sourceEvent:n,subject:e,target:r,identifier:i,active:o,x:a,y:u,dx:s,dy:l,dispatch:c}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},subject:{value:e,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:i,enumerable:!0,configurable:!0},active:{value:o,enumerable:!0,configurable:!0},x:{value:a,enumerable:!0,configurable:!0},y:{value:u,enumerable:!0,configurable:!0},dx:{value:s,enumerable:!0,configurable:!0},dy:{value:l,enumerable:!0,configurable:!0},_:{value:c}})}function Ut(t){return!t.ctrlKey&&!t.button}function Ft(){return this.parentNode}function Lt(t,n){return null==n?{x:t.x,y:t.y}:n}function qt(){return navigator.maxTouchPoints||"ontouchstart"in this}function Bt(t,n,e){t.prototype=n.prototype=e,e.constructor=t}function $t(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function Ht(){}It.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var Vt=.7,Xt=1/Vt,Gt="\\s*([+-]?\\d+)\\s*",Yt="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",Wt="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Zt=/^#([0-9a-f]{3,8})$/,Qt=new RegExp(`^rgb\\(${Gt},${Gt},${Gt}\\)$`),Kt=new RegExp(`^rgb\\(${Wt},${Wt},${Wt}\\)$`),Jt=new RegExp(`^rgba\\(${Gt},${Gt},${Gt},${Yt}\\)$`),tn=new RegExp(`^rgba\\(${Wt},${Wt},${Wt},${Yt}\\)$`),nn=new RegExp(`^hsl\\(${Yt},${Wt},${Wt}\\)$`),en=new RegExp(`^hsla\\(${Yt},${Wt},${Wt},${Yt}\\)$`),rn={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function on(){return this.rgb().formatHex()}function an(){return this.rgb().formatRgb()}function un(t){var n,e;return t=(t+"").trim().toLowerCase(),(n=Zt.exec(t))?(e=n[1].length,n=parseInt(n[1],16),6===e?sn(n):3===e?new hn(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1):8===e?ln(n>>24&255,n>>16&255,n>>8&255,(255&n)/255):4===e?ln(n>>12&15|n>>8&240,n>>8&15|n>>4&240,n>>4&15|240&n,((15&n)<<4|15&n)/255):null):(n=Qt.exec(t))?new hn(n[1],n[2],n[3],1):(n=Kt.exec(t))?new hn(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=Jt.exec(t))?ln(n[1],n[2],n[3],n[4]):(n=tn.exec(t))?ln(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=nn.exec(t))?vn(n[1],n[2]/100,n[3]/100,1):(n=en.exec(t))?vn(n[1],n[2]/100,n[3]/100,n[4]):rn.hasOwnProperty(t)?sn(rn[t]):"transparent"===t?new hn(NaN,NaN,NaN,0):null}function sn(t){return new hn(t>>16&255,t>>8&255,255&t,1)}function ln(t,n,e,r){return r<=0&&(t=n=e=NaN),new hn(t,n,e,r)}function cn(t,n,e,r){return 1===arguments.length?((i=t)instanceof Ht||(i=un(i)),i?new hn((i=i.rgb()).r,i.g,i.b,i.opacity):new hn):new hn(t,n,e,null==r?1:r);var i}function hn(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function fn(){return`#${yn(this.r)}${yn(this.g)}${yn(this.b)}`}function dn(){const t=pn(this.opacity);return`${1===t?"rgb(":"rgba("}${gn(this.r)}, ${gn(this.g)}, ${gn(this.b)}${1===t?")":`, ${t})`}`}function pn(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function gn(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function yn(t){return((t=gn(t))<16?"0":"")+t.toString(16)}function vn(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new mn(t,n,e,r)}function _n(t){if(t instanceof mn)return new mn(t.h,t.s,t.l,t.opacity);if(t instanceof Ht||(t=un(t)),!t)return new mn;if(t instanceof mn)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),a=NaN,u=o-i,s=(o+i)/2;return u?(a=n===o?(e-r)/u+6*(e0&&s<1?0:a,new mn(a,u,s,t.opacity)}function mn(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function xn(t){return(t=(t||0)%360)<0?t+360:t}function bn(t){return Math.max(0,Math.min(1,t||0))}function wn(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}Bt(Ht,un,{copy(t){return Object.assign(new this.constructor,this,t)},displayable(){return this.rgb().displayable()},hex:on,formatHex:on,formatHex8:function(){return this.rgb().formatHex8()},formatHsl:function(){return _n(this).formatHsl()},formatRgb:an,toString:an}),Bt(hn,cn,$t(Ht,{brighter(t){return t=null==t?Xt:Math.pow(Xt,t),new hn(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=null==t?Vt:Math.pow(Vt,t),new hn(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new hn(gn(this.r),gn(this.g),gn(this.b),pn(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:fn,formatHex:fn,formatHex8:function(){return`#${yn(this.r)}${yn(this.g)}${yn(this.b)}${yn(255*(isNaN(this.opacity)?1:this.opacity))}`},formatRgb:dn,toString:dn})),Bt(mn,(function(t,n,e,r){return 1===arguments.length?_n(t):new mn(t,n,e,null==r?1:r)}),$t(Ht,{brighter(t){return t=null==t?Xt:Math.pow(Xt,t),new mn(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=null==t?Vt:Math.pow(Vt,t),new mn(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new hn(wn(t>=240?t-240:t+120,i,r),wn(t,i,r),wn(t<120?t+240:t-120,i,r),this.opacity)},clamp(){return new mn(xn(this.h),bn(this.s),bn(this.l),pn(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=pn(this.opacity);return`${1===t?"hsl(":"hsla("}${xn(this.h)}, ${100*bn(this.s)}%, ${100*bn(this.l)}%${1===t?")":`, ${t})`}`}}));var kn=t=>()=>t;function Mn(t){return 1==(t=+t)?zn:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):kn(isNaN(n)?e:n)}}function zn(t,n){var e=n-t;return e?function(t,n){return function(e){return t+e*n}}(t,e):kn(isNaN(t)?n:t)}var An=function t(n){var e=Mn(n);function r(t,n){var r=e((t=cn(t)).r,(n=cn(n)).r),i=e(t.g,n.g),o=e(t.b,n.b),a=zn(t.opacity,n.opacity);return function(n){return t.r=r(n),t.g=i(n),t.b=o(n),t.opacity=a(n),t+""}}return r.gamma=t,r}(1);function Sn(t,n){return t=+t,n=+n,function(e){return t*(1-e)+n*e}}var Cn=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,En=new RegExp(Cn.source,"g");function On(t,n){var e,r,i,o=Cn.lastIndex=En.lastIndex=0,a=-1,u=[],s=[];for(t+="",n+="";(e=Cn.exec(t))&&(r=En.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),u[a]?u[a]+=i:u[++a]=i),(e=e[0])===(r=r[0])?u[a]?u[a]+=r:u[++a]=r:(u[++a]=null,s.push({i:a,x:Sn(e,r)})),o=En.lastIndex;return o180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:Sn(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}(o.rotate,a.rotate,u,s),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:Sn(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}(o.skewX,a.skewX,u,s),function(t,n,e,r,o,a){if(t!==e||n!==r){var u=o.push(i(o)+"scale(",null,",",null,")");a.push({i:u-4,x:Sn(t,e)},{i:u-2,x:Sn(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,u,s),o=a=null,function(t){for(var n,e=-1,r=s.length;++e=0&&n._call.call(void 0,t),n=n._next;--Bn}()}finally{Bn=0,function(){var t,n,e=Fn,r=1/0;for(;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Fn=n);Ln=t,re(r)}(),Gn=0}}function ee(){var t=Wn.now(),n=t-Xn;n>Vn&&(Yn-=n,Xn=t)}function re(t){Bn||($n&&($n=clearTimeout($n)),t-Gn>24?(t<1/0&&($n=setTimeout(ne,t-Wn.now()-Yn)),Hn&&(Hn=clearInterval(Hn))):(Hn||(Xn=Wn.now(),Hn=setInterval(ee,Vn)),Bn=1,Zn(ne)))}function ie(t,n,e){var r=new Jn;return n=null==n?0:+n,r.restart((e=>{r.stop(),t(e+n)}),n,e),r}Jn.prototype=te.prototype={constructor:Jn,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?Qn():+e)+(null==n?0:+n),this._next||Ln===this||(Ln?Ln._next=this:Fn=this,Ln=this),this._call=t,this._time=e,re()},stop:function(){this._call&&(this._call=null,this._time=1/0,re())}};var oe=At("start","end","cancel","interrupt"),ae=[],ue=0,se=1,le=2,ce=3,he=4,fe=5,de=6;function pe(t,n,e,r,i,o){var a=t.__transition;if(a){if(e in a)return}else t.__transition={};!function(t,n,e){var r,i=t.__transition;function o(t){e.state=se,e.timer.restart(a,e.delay,e.time),e.delay<=t&&a(t-e.delay)}function a(o){var l,c,h,f;if(e.state!==se)return s();for(l in i)if((f=i[l]).name===e.name){if(f.state===ce)return ie(a);f.state===he?(f.state=de,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[l]):+lue)throw new Error("too late; already scheduled");return e}function ye(t,n){var e=ve(t,n);if(e.state>ce)throw new Error("too late; already running");return e}function ve(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("transition not found");return e}function _e(t,n){var e,r,i,o=t.__transition,a=!0;if(o){for(i in n=null==n?null:n+"",o)(e=o[i]).name===n?(r=e.state>le&&e.state=0&&(t=t.slice(0,n)),!t||"start"===t}))}(n)?ge:ye;return function(){var a=o(this,t),u=a.on;u!==r&&(i=(r=u).copy()).on(n,e),a.on=i}}(e,t,n))},attr:function(t,n){var e=d(t),r="transform"===e?In:we;return this.attrTween(t,"function"==typeof n?(e.local?Ce:Se)(e,r,be(this,"attr."+t,n)):null==n?(e.local?Me:ke)(e):(e.local?Ae:ze)(e,r,n))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=d(t);return this.tween(e,(r.local?Ee:Oe)(r,n))},style:function(t,n,e){var r="transform"==(t+="")?Dn:we;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=V(this,t),a=(this.style.removeProperty(t),V(this,t));return o===a?null:o===e&&a===r?i:i=n(e=o,r=a)}}(t,r)).on("end.style."+t,De(t)):"function"==typeof n?this.styleTween(t,function(t,n,e){var r,i,o;return function(){var a=V(this,t),u=e(this),s=u+"";return null==u&&(this.style.removeProperty(t),s=u=V(this,t)),a===s?null:a===r&&s===i?o:(i=s,o=n(r=a,u))}}(t,r,be(this,"style."+t,n))).each(function(t,n){var e,r,i,o,a="style."+n,u="end."+a;return function(){var s=ye(this,t),l=s.on,c=null==s.value[a]?o||(o=De(n)):void 0;l===e&&i===c||(r=(e=l).copy()).on(u,i=c),s.on=r}}(this._id,t)):this.styleTween(t,function(t,n,e){var r,i,o=e+"";return function(){var a=V(this,t);return a===o?null:a===r?i:i=n(r=a,e)}}(t,r,n),e).on("end.style."+t,null)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,function(t,n,e){var r,i;function o(){var o=n.apply(this,arguments);return o!==i&&(r=(i=o)&&function(t,n,e){return function(r){this.style.setProperty(t,n.call(this,r),e)}}(t,o,e)),r}return o._value=n,o}(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?"":n}}(be(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var n="text";if(arguments.length<1)return(n=this.tween(n))&&n._value;if(null==t)return this.tween(n,null);if("function"!=typeof t)throw new Error;return this.tween(n,function(t){var n,e;function r(){var r=t.apply(this,arguments);return r!==e&&(n=(e=r)&&function(t){return function(n){this.textContent=t.call(this,n)}}(r)),n}return r._value=t,r}(t))},remove:function(){return this.on("end.remove",function(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=ve(this.node(),e).tween,o=0,a=i.length;o()=>t;function He(t,{sourceEvent:n,target:e,transform:r,dispatch:i}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},target:{value:e,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:i}})}function Ve(t,n,e){this.k=t,this.x=n,this.y=e}Ve.prototype={constructor:Ve,scale:function(t){return 1===t?this:new Ve(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new Ve(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Xe=new Ve(1,0,0);function Ge(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Xe;return t.__zoom}function Ye(t){t.stopImmediatePropagation()}function We(t){t.preventDefault(),t.stopImmediatePropagation()}function Ze(t){return!(t.ctrlKey&&"wheel"!==t.type||t.button)}function Qe(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t).hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]:[[0,0],[t.clientWidth,t.clientHeight]]}function Ke(){return this.__zoom||Xe}function Je(t){return-t.deltaY*(1===t.deltaMode?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function tr(){return navigator.maxTouchPoints||"ontouchstart"in this}function nr(t,n,e){var r=t.invertX(n[0][0])-e[0][0],i=t.invertX(n[1][0])-e[1][0],o=t.invertY(n[0][1])-e[0][1],a=t.invertY(n[1][1])-e[1][1];return t.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),a>o?(o+a)/2:Math.min(0,o)||Math.max(0,a))}function er(){var t,n,e,r=Ze,i=Qe,o=nr,a=Je,u=tr,s=[0,1/0],l=[[-1/0,-1/0],[1/0,1/0]],c=250,h=qn,f=At("start","zoom","end"),d=500,p=150,g=0,y=10;function v(t){t.property("__zoom",Ke).on("wheel.zoom",M,{passive:!1}).on("mousedown.zoom",z).on("dblclick.zoom",A).filter(u).on("touchstart.zoom",S).on("touchmove.zoom",C).on("touchend.zoom touchcancel.zoom",E).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(t,n){return(n=Math.max(s[0],Math.min(s[1],n)))===t.k?t:new Ve(n,t.x,t.y)}function m(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new Ve(t.k,r,i)}function x(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function b(t,n,e,r){t.on("start.zoom",(function(){w(this,arguments).event(r).start()})).on("interrupt.zoom end.zoom",(function(){w(this,arguments).event(r).end()})).tween("zoom",(function(){var t=this,o=arguments,a=w(t,o).event(r),u=i.apply(t,o),s=null==e?x(u):"function"==typeof e?e.apply(t,o):e,l=Math.max(u[1][0]-u[0][0],u[1][1]-u[0][1]),c=t.__zoom,f="function"==typeof n?n.apply(t,o):n,d=h(c.invert(s).concat(l/c.k),f.invert(s).concat(l/f.k));return function(t){if(1===t)t=f;else{var n=d(t),e=l/n[2];t=new Ve(e,s[0]-n[0]*e,s[1]-n[1]*e)}a.zoom(null,t)}}))}function w(t,n,e){return!e&&t.__zooming||new k(t,n)}function k(t,n){this.that=t,this.args=n,this.active=0,this.sourceEvent=null,this.extent=i.apply(t,n),this.taps=0}function M(t,...n){if(r.apply(this,arguments)){var e=w(this,n).event(t),i=this.__zoom,u=Math.max(s[0],Math.min(s[1],i.k*Math.pow(2,a.apply(this,arguments)))),c=Mt(t);if(e.wheel)e.mouse[0][0]===c[0]&&e.mouse[0][1]===c[1]||(e.mouse[1]=i.invert(e.mouse[0]=c)),clearTimeout(e.wheel);else{if(i.k===u)return;e.mouse=[c,i.invert(c)],_e(this),e.start()}We(t),e.wheel=setTimeout((function(){e.wheel=null,e.end()}),p),e.zoom("mouse",o(m(_(i,u),e.mouse[0],e.mouse[1]),e.extent,l))}}function z(t,...n){if(!e&&r.apply(this,arguments)){var i=t.currentTarget,a=w(this,n,!0).event(t),u=kt(t.view).on("mousemove.zoom",(function(t){if(We(t),!a.moved){var n=t.clientX-c,e=t.clientY-h;a.moved=n*n+e*e>g}a.event(t).zoom("mouse",o(m(a.that.__zoom,a.mouse[0]=Mt(t,i),a.mouse[1]),a.extent,l))}),!0).on("mouseup.zoom",(function(t){u.on("mousemove.zoom mouseup.zoom",null),Rt(t.view,a.moved),We(t),a.event(t).end()}),!0),s=Mt(t,i),c=t.clientX,h=t.clientY;Tt(t.view),Ye(t),a.mouse=[s,this.__zoom.invert(s)],_e(this),a.start()}}function A(t,...n){if(r.apply(this,arguments)){var e=this.__zoom,a=Mt(t.changedTouches?t.changedTouches[0]:t,this),u=e.invert(a),s=e.k*(t.shiftKey?.5:2),h=o(m(_(e,s),a,u),i.apply(this,n),l);We(t),c>0?kt(this).transition().duration(c).call(b,h,a,t):kt(this).call(v.transform,h,a,t)}}function S(e,...i){if(r.apply(this,arguments)){var o,a,u,s,l=e.touches,c=l.length,h=w(this,i,e.changedTouches.length===c).event(e);for(Ye(e),a=0;a=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e=i)&&(e=i)}return e}function ur(t,n){let e;if(void 0===n)for(const n of t)null!=n&&(e>n||void 0===e&&n>=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e>i||void 0===e&&i>=i)&&(e=i)}return e}var sr="object"==typeof global&&global&&global.Object===Object&&global,lr="object"==typeof self&&self&&self.Object===Object&&self,cr=sr||lr||Function("return this")(),hr=cr.Symbol,fr=Object.prototype,dr=fr.hasOwnProperty,pr=fr.toString,gr=hr?hr.toStringTag:void 0;var yr=Object.prototype.toString;var vr="[object Null]",_r="[object Undefined]",mr=hr?hr.toStringTag:void 0;function xr(t){return null==t?void 0===t?_r:vr:mr&&mr in Object(t)?function(t){var n=dr.call(t,gr),e=t[gr];try{t[gr]=void 0;var r=!0}catch(t){}var i=pr.call(t);return r&&(n?t[gr]=e:delete t[gr]),i}(t):function(t){return yr.call(t)}(t)}var br="[object Symbol]";var wr=/\s/;var kr=/^\s+/;function Mr(t){return t?t.slice(0,function(t){for(var n=t.length;n--&&wr.test(t.charAt(n)););return n}(t)+1).replace(kr,""):t}function zr(t){var n=typeof t;return null!=t&&("object"==n||"function"==n)}var Ar=NaN,Sr=/^[-+]0x[0-9a-f]+$/i,Cr=/^0b[01]+$/i,Er=/^0o[0-7]+$/i,Or=parseInt;function Nr(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return null!=t&&"object"==typeof t}(t)&&xr(t)==br}(t))return Ar;if(zr(t)){var n="function"==typeof t.valueOf?t.valueOf():t;t=zr(n)?n+"":n}if("string"!=typeof t)return 0===t?t:+t;t=Mr(t);var e=Cr.test(t);return e||Er.test(t)?Or(t.slice(2),e?2:8):Sr.test(t)?Ar:+t}var Pr=function(){return cr.Date.now()},jr="Expected a function",Tr=Math.max,Rr=Math.min;function Dr(t,n,e){var r,i,o,a,u,s,l=0,c=!1,h=!1,f=!0;if("function"!=typeof t)throw new TypeError(jr);function d(n){var e=r,o=i;return r=i=void 0,l=n,a=t.apply(o,e)}function p(t){var e=t-s;return void 0===s||e>=n||e<0||h&&t-l>=o}function g(){var t=Pr();if(p(t))return y(t);u=setTimeout(g,function(t){var e=n-(t-s);return h?Rr(e,o-(t-l)):e}(t))}function y(t){return u=void 0,f&&r?d(t):(r=i=void 0,a)}function v(){var t=Pr(),e=p(t);if(r=arguments,i=this,s=t,e){if(void 0===u)return function(t){return l=t,u=setTimeout(g,n),c?d(t):a}(s);if(h)return clearTimeout(u),u=setTimeout(g,n),d(s)}return void 0===u&&(u=setTimeout(g,n)),a}return n=Nr(n)||0,zr(e)&&(c=!!e.leading,o=(h="maxWait"in e)?Tr(Nr(e.maxWait)||0,n):o,f="trailing"in e?!!e.trailing:f),v.cancel=function(){void 0!==u&&clearTimeout(u),l=0,r=s=i=u=void 0},v.flush=function(){return void 0===u?a:y(Pr())},v}var Ir=Object.freeze({Linear:Object.freeze({None:function(t){return t},In:function(t){return this.None(t)},Out:function(t){return this.None(t)},InOut:function(t){return this.None(t)}}),Quadratic:Object.freeze({In:function(t){return t*t},Out:function(t){return t*(2-t)},InOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)}}),Cubic:Object.freeze({In:function(t){return t*t*t},Out:function(t){return--t*t*t+1},InOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)}}),Quartic:Object.freeze({In:function(t){return t*t*t*t},Out:function(t){return 1- --t*t*t*t},InOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)}}),Quintic:Object.freeze({In:function(t){return t*t*t*t*t},Out:function(t){return--t*t*t*t*t+1},InOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)}}),Sinusoidal:Object.freeze({In:function(t){return 1-Math.sin((1-t)*Math.PI/2)},Out:function(t){return Math.sin(t*Math.PI/2)},InOut:function(t){return.5*(1-Math.sin(Math.PI*(.5-t)))}}),Exponential:Object.freeze({In:function(t){return 0===t?0:Math.pow(1024,t-1)},Out:function(t){return 1===t?1:1-Math.pow(2,-10*t)},InOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))}}),Circular:Object.freeze({In:function(t){return 1-Math.sqrt(1-t*t)},Out:function(t){return Math.sqrt(1- --t*t)},InOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)}}),Elastic:Object.freeze({In:function(t){return 0===t?0:1===t?1:-Math.pow(2,10*(t-1))*Math.sin(5*(t-1.1)*Math.PI)},Out:function(t){return 0===t?0:1===t?1:Math.pow(2,-10*t)*Math.sin(5*(t-.1)*Math.PI)+1},InOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?-.5*Math.pow(2,10*(t-1))*Math.sin(5*(t-1.1)*Math.PI):.5*Math.pow(2,-10*(t-1))*Math.sin(5*(t-1.1)*Math.PI)+1}}),Back:Object.freeze({In:function(t){var n=1.70158;return 1===t?1:t*t*((n+1)*t-n)},Out:function(t){var n=1.70158;return 0===t?0:--t*t*((n+1)*t+n)+1},InOut:function(t){var n=2.5949095;return(t*=2)<1?t*t*((n+1)*t-n)*.5:.5*((t-=2)*t*((n+1)*t+n)+2)}}),Bounce:Object.freeze({In:function(t){return 1-Ir.Bounce.Out(1-t)},Out:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},InOut:function(t){return t<.5?.5*Ir.Bounce.In(2*t):.5*Ir.Bounce.Out(2*t-1)+.5}}),generatePow:function(t){return void 0===t&&(t=4),t=(t=t1e4?1e4:t,{In:function(n){return Math.pow(n,t)},Out:function(n){return 1-Math.pow(1-n,t)},InOut:function(n){return n<.5?Math.pow(2*n,t)/2:(1-Math.pow(2-2*n,t))/2+.5}}}}),Ur=function(){return performance.now()},Fr=function(){function t(){this._tweens={},this._tweensAddedDuringUpdate={}}return t.prototype.getAll=function(){var t=this;return Object.keys(this._tweens).map((function(n){return t._tweens[n]}))},t.prototype.removeAll=function(){this._tweens={}},t.prototype.add=function(t){this._tweens[t.getId()]=t,this._tweensAddedDuringUpdate[t.getId()]=t},t.prototype.remove=function(t){delete this._tweens[t.getId()],delete this._tweensAddedDuringUpdate[t.getId()]},t.prototype.update=function(t,n){void 0===t&&(t=Ur()),void 0===n&&(n=!1);var e=Object.keys(this._tweens);if(0===e.length)return!1;for(;e.length>0;){this._tweensAddedDuringUpdate={};for(var r=0;r1?o(t[e],t[e-1],e-r):o(t[i],t[i+1>e?e:i+1],r-i)},Bezier:function(t,n){for(var e=0,r=t.length-1,i=Math.pow,o=Lr.Utils.Bernstein,a=0;a<=r;a++)e+=i(1-n,r-a)*i(n,a)*t[a]*o(r,a);return e},CatmullRom:function(t,n){var e=t.length-1,r=e*n,i=Math.floor(r),o=Lr.Utils.CatmullRom;return t[0]===t[e]?(n<0&&(i=Math.floor(r=e*(1+n))),o(t[(i-1+e)%e],t[i],t[(i+1)%e],t[(i+2)%e],r-i)):n<0?t[0]-(o(t[0],t[0],t[1],t[1],-r)-t[0]):n>1?t[e]-(o(t[e],t[e],t[e-1],t[e-1],r-e)-t[e]):o(t[i?i-1:0],t[i],t[e1;r--)e*=r;return t[n]=e,e}}(),CatmullRom:function(t,n,e,r,i){var o=.5*(e-t),a=.5*(r-n),u=i*i;return(2*n-2*e+o+a)*(i*u)+(-3*n+3*e-2*o-a)*u+o*i+n}}},qr=function(){function t(){}return t.nextId=function(){return t._nextId++},t._nextId=0,t}(),Br=new Fr,$r=function(){function t(t,n){void 0===n&&(n=Br),this._object=t,this._group=n,this._isPaused=!1,this._pauseStart=0,this._valuesStart={},this._valuesEnd={},this._valuesStartRepeat={},this._duration=1e3,this._isDynamic=!1,this._initialRepeat=0,this._repeat=0,this._yoyo=!1,this._isPlaying=!1,this._reversed=!1,this._delayTime=0,this._startTime=0,this._easingFunction=Ir.Linear.None,this._interpolationFunction=Lr.Linear,this._chainedTweens=[],this._onStartCallbackFired=!1,this._onEveryStartCallbackFired=!1,this._id=qr.nextId(),this._isChainStopped=!1,this._propertiesAreSetUp=!1,this._goToEnd=!1}return t.prototype.getId=function(){return this._id},t.prototype.isPlaying=function(){return this._isPlaying},t.prototype.isPaused=function(){return this._isPaused},t.prototype.to=function(t,n){if(void 0===n&&(n=1e3),this._isPlaying)throw new Error("Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.");return this._valuesEnd=t,this._propertiesAreSetUp=!1,this._duration=n,this},t.prototype.duration=function(t){return void 0===t&&(t=1e3),this._duration=t,this},t.prototype.dynamic=function(t){return void 0===t&&(t=!1),this._isDynamic=t,this},t.prototype.start=function(t,n){if(void 0===t&&(t=Ur()),void 0===n&&(n=!1),this._isPlaying)return this;if(this._group&&this._group.add(this),this._repeat=this._initialRepeat,this._reversed)for(var e in this._reversed=!1,this._valuesStartRepeat)this._swapEndStartRepeatValues(e),this._valuesStart[e]=this._valuesStartRepeat[e];if(this._isPlaying=!0,this._isPaused=!1,this._onStartCallbackFired=!1,this._onEveryStartCallbackFired=!1,this._isChainStopped=!1,this._startTime=t,this._startTime+=this._delayTime,!this._propertiesAreSetUp||n){if(this._propertiesAreSetUp=!0,!this._isDynamic){var r={};for(var i in this._valuesEnd)r[i]=this._valuesEnd[i];this._valuesEnd=r}this._setupProperties(this._object,this._valuesStart,this._valuesEnd,this._valuesStartRepeat,n)}return this},t.prototype.startFromCurrentValues=function(t){return this.start(t,!0)},t.prototype._setupProperties=function(t,n,e,r,i){for(var o in e){var a=t[o],u=Array.isArray(a),s=u?"array":typeof a,l=!u&&Array.isArray(e[o]);if("undefined"!==s&&"function"!==s){if(l){if(0===(y=e[o]).length)continue;for(var c=[a],h=0,f=y.length;hi)return!1;n&&this.start(t,!0)}if(this._goToEnd=!1,t1?1:r;var o=this._easingFunction(r);if(this._updateProperties(this._object,this._valuesStart,this._valuesEnd,o),this._onUpdateCallback&&this._onUpdateCallback(this._object,r),1===r){if(this._repeat>0){for(e in isFinite(this._repeat)&&this._repeat--,this._valuesStartRepeat)this._yoyo||"string"!=typeof this._valuesEnd[e]||(this._valuesStartRepeat[e]=this._valuesStartRepeat[e]+parseFloat(this._valuesEnd[e])),this._yoyo&&this._swapEndStartRepeatValues(e),this._valuesStart[e]=this._valuesStartRepeat[e];return this._yoyo&&(this._reversed=!this._reversed),void 0!==this._repeatDelayTime?this._startTime=t+this._repeatDelayTime:this._startTime=t+this._delayTime,this._onRepeatCallback&&this._onRepeatCallback(this._object),this._onEveryStartCallbackFired=!1,!0}this._onCompleteCallback&&this._onCompleteCallback(this._object);for(var a=0,u=this._chainedTweens.length;at.length)&&(n=t.length);for(var e=0,r=new Array(n);e0&&void 0!==arguments[0]?arguments[0]:{},n=Object.assign({},e instanceof Function?e(t):e,{initialised:!1}),r={};function i(n){return o(n,t),u(),i}var o=function(t,e){c.call(i,t,n,e),n.initialised=!0},u=Dr((function(){n.initialised&&(f.call(i,n,r),r={})}),1);return d.forEach((function(t){i[t.name]=function(t){var e=t.name,o=t.triggerUpdate,a=void 0!==o&&o,s=t.onChange,l=void 0===s?function(t,n){}:s,c=t.defaultVal,h=void 0===c?null:c;return function(t){var o=n[e];if(!arguments.length)return o;var s=void 0===t?h:t;return n[e]=s,l.call(i,s,n,o),!r.hasOwnProperty(e)&&(r[e]=o),a&&u(),i}}(t)})),Object.keys(a).forEach((function(t){i[t]=function(){for(var e,r=arguments.length,o=new Array(r),u=0;u1&&(e-=1),e<1/6?t+6*(n-t)*e:e<.5?n:e<2/3?t+(n-t)*(2/3-e)*6:t}if(t=wi(t,360),n=wi(n,100),e=wi(e,100),0===n)r=i=o=e;else{var u=e<.5?e*(1+n):e+n-e*n,s=2*e-u;r=a(s,u,t+1/3),i=a(s,u,t),o=a(s,u,t-1/3)}return{r:255*r,g:255*i,b:255*o}}(t.h,r,o),a=!0,u="hsl"),t.hasOwnProperty("a")&&(e=t.a));var s,l,c;return e=bi(e),{ok:a,format:t.format||u,r:Math.min(255,Math.max(n.r,0)),g:Math.min(255,Math.max(n.g,0)),b:Math.min(255,Math.max(n.b,0)),a:e}}(t);this._originalInput=t,this._r=e.r,this._g=e.g,this._b=e.b,this._a=e.a,this._roundA=Math.round(100*this._a)/100,this._format=n.format||e.format,this._gradientType=n.gradientType,this._r<1&&(this._r=Math.round(this._r)),this._g<1&&(this._g=Math.round(this._g)),this._b<1&&(this._b=Math.round(this._b)),this._ok=e.ok}function ri(t,n,e){t=wi(t,255),n=wi(n,255),e=wi(e,255);var r,i,o=Math.max(t,n,e),a=Math.min(t,n,e),u=(o+a)/2;if(o==a)r=i=0;else{var s=o-a;switch(i=u>.5?s/(2-o-a):s/(o+a),o){case t:r=(n-e)/s+(n>1)+720)%360;--n;)r.h=(r.h+i)%360,o.push(ei(r));return o}function _i(t,n){n=n||6;for(var e=ei(t).toHsv(),r=e.h,i=e.s,o=e.v,a=[],u=1/n;n--;)a.push(ei({h:r,s:i,v:o})),o=(o+u)%1;return a}ei.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},getLuminance:function(){var t,n,e,r=this.toRgb();return t=r.r/255,n=r.g/255,e=r.b/255,.2126*(t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4))+.7152*(n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4))+.0722*(e<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4))},setAlpha:function(t){return this._a=bi(t),this._roundA=Math.round(100*this._a)/100,this},toHsv:function(){var t=ii(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=ii(this._r,this._g,this._b),n=Math.round(360*t.h),e=Math.round(100*t.s),r=Math.round(100*t.v);return 1==this._a?"hsv("+n+", "+e+"%, "+r+"%)":"hsva("+n+", "+e+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var t=ri(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=ri(this._r,this._g,this._b),n=Math.round(360*t.h),e=Math.round(100*t.s),r=Math.round(100*t.l);return 1==this._a?"hsl("+n+", "+e+"%, "+r+"%)":"hsla("+n+", "+e+"%, "+r+"%, "+this._roundA+")"},toHex:function(t){return oi(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(t){return function(t,n,e,r,i){var o=[zi(Math.round(t).toString(16)),zi(Math.round(n).toString(16)),zi(Math.round(e).toString(16)),zi(Si(r))];if(i&&o[0].charAt(0)==o[0].charAt(1)&&o[1].charAt(0)==o[1].charAt(1)&&o[2].charAt(0)==o[2].charAt(1)&&o[3].charAt(0)==o[3].charAt(1))return o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0);return o.join("")}(this._r,this._g,this._b,this._a,t)},toHex8String:function(t){return"#"+this.toHex8(t)},toRgb:function(){return{r:Math.round(this._r),g:Math.round(this._g),b:Math.round(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+")":"rgba("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:Math.round(100*wi(this._r,255))+"%",g:Math.round(100*wi(this._g,255))+"%",b:Math.round(100*wi(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+Math.round(100*wi(this._r,255))+"%, "+Math.round(100*wi(this._g,255))+"%, "+Math.round(100*wi(this._b,255))+"%)":"rgba("+Math.round(100*wi(this._r,255))+"%, "+Math.round(100*wi(this._g,255))+"%, "+Math.round(100*wi(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(xi[oi(this._r,this._g,this._b,!0)]||!1)},toFilter:function(t){var n="#"+ai(this._r,this._g,this._b,this._a),e=n,r=this._gradientType?"GradientType = 1, ":"";if(t){var i=ei(t);e="#"+ai(i._r,i._g,i._b,i._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+n+",endColorstr="+e+")"},toString:function(t){var n=!!t;t=t||this._format;var e=!1,r=this._a<1&&this._a>=0;return n||!r||"hex"!==t&&"hex6"!==t&&"hex3"!==t&&"hex4"!==t&&"hex8"!==t&&"name"!==t?("rgb"===t&&(e=this.toRgbString()),"prgb"===t&&(e=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(e=this.toHexString()),"hex3"===t&&(e=this.toHexString(!0)),"hex4"===t&&(e=this.toHex8String(!0)),"hex8"===t&&(e=this.toHex8String()),"name"===t&&(e=this.toName()),"hsl"===t&&(e=this.toHslString()),"hsv"===t&&(e=this.toHsvString()),e||this.toHexString()):"name"===t&&0===this._a?this.toName():this.toRgbString()},clone:function(){return ei(this.toString())},_applyModification:function(t,n){var e=t.apply(null,[this].concat([].slice.call(n)));return this._r=e._r,this._g=e._g,this._b=e._b,this.setAlpha(e._a),this},lighten:function(){return this._applyModification(ci,arguments)},brighten:function(){return this._applyModification(hi,arguments)},darken:function(){return this._applyModification(fi,arguments)},desaturate:function(){return this._applyModification(ui,arguments)},saturate:function(){return this._applyModification(si,arguments)},greyscale:function(){return this._applyModification(li,arguments)},spin:function(){return this._applyModification(di,arguments)},_applyCombination:function(t,n){return t.apply(null,[this].concat([].slice.call(n)))},analogous:function(){return this._applyCombination(vi,arguments)},complement:function(){return this._applyCombination(pi,arguments)},monochromatic:function(){return this._applyCombination(_i,arguments)},splitcomplement:function(){return this._applyCombination(yi,arguments)},triad:function(){return this._applyCombination(gi,[3])},tetrad:function(){return this._applyCombination(gi,[4])}},ei.fromRatio=function(t,n){if("object"==Jr(t)){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[r]="a"===r?t[r]:Ai(t[r]));t=e}return ei(t,n)},ei.equals=function(t,n){return!(!t||!n)&&ei(t).toRgbString()==ei(n).toRgbString()},ei.random=function(){return ei.fromRatio({r:Math.random(),g:Math.random(),b:Math.random()})},ei.mix=function(t,n,e){e=0===e?0:e||50;var r=ei(t).toRgb(),i=ei(n).toRgb(),o=e/100;return ei({r:(i.r-r.r)*o+r.r,g:(i.g-r.g)*o+r.g,b:(i.b-r.b)*o+r.b,a:(i.a-r.a)*o+r.a})}, -// =4.5;break;case"AAlarge":i=o>=3;break;case"AAAsmall":i=o>=7}return i},ei.mostReadable=function(t,n,e){var r,i,o,a,u=null,s=0;i=(e=e||{}).includeFallbackColors,o=e.level,a=e.size;for(var l=0;ls&&(s=r,u=ei(n[l]));return ei.isReadable(t,u,{level:o,size:a})||!i?u:(e.includeFallbackColors=!1,ei.mostReadable(t,["#fff","#000"],e))};var mi=ei.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},xi=ei.hexNames=function(t){var n={};for(var e in t)t.hasOwnProperty(e)&&(n[t[e]]=e);return n}(mi);function bi(t){return t=parseFloat(t),(isNaN(t)||t<0||t>1)&&(t=1),t}function wi(t,n){(function(t){return"string"==typeof t&&-1!=t.indexOf(".")&&1===parseFloat(t)})(t)&&(t="100%");var e=function(t){return"string"==typeof t&&-1!=t.indexOf("%")}(t);return t=Math.min(n,Math.max(0,parseFloat(t))),e&&(t=parseInt(t*n,10)/100),Math.abs(t-n)<1e-6?1:t%n/parseFloat(n)}function ki(t){return Math.min(1,Math.max(0,t))}function Mi(t){return parseInt(t,16)}function zi(t){return 1==t.length?"0"+t:""+t}function Ai(t){return t<=1&&(t=100*t+"%"),t}function Si(t){return Math.round(255*parseFloat(t)).toString(16)}function Ci(t){return Mi(t)/255}var Ei,Oi,Ni,Pi=(Oi="[\\s|\\(]+("+(Ei="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+Ei+")[,|\\s]+("+Ei+")\\s*\\)?",Ni="[\\s|\\(]+("+Ei+")[,|\\s]+("+Ei+")[,|\\s]+("+Ei+")[,|\\s]+("+Ei+")\\s*\\)?",{CSS_UNIT:new RegExp(Ei),rgb:new RegExp("rgb"+Oi),rgba:new RegExp("rgba"+Ni),hsl:new RegExp("hsl"+Oi),hsla:new RegExp("hsla"+Ni),hsv:new RegExp("hsv"+Oi),hsva:new RegExp("hsva"+Ni),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function ji(t){return!!Pi.CSS_UNIT.exec(t)}function Ti(t,n){for(var e=0;et.length)&&(n=t.length);for(var e=0,r=new Array(n);e0&&void 0!==arguments[0]?arguments[0]:6;!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.csBits=n,this.registry=["__reserved for background__"]}var n,e,r;return n=t,e=[{key:"register",value:function(t){if(this.registry.length>=Math.pow(2,24-this.csBits))return null;var n,e=this.registry.length,r=Ui(e,this.csBits),i=(n=e+(r<<24-this.csBits),"#".concat(Math.min(n,Math.pow(2,24)).toString(16).padStart(6,"0")));return this.registry.push(t),i}},{key:"lookup",value:function(t){var n,e,r,i,o="string"==typeof t?(n=ei(t).toRgb(),e=n.r,r=n.g,i=n.b,Ii(e,r,i)):Ii.apply(void 0,Ri(t));if(!o)return null;var a=o&Math.pow(2,24-this.csBits)-1,u=o>>24-this.csBits&Math.pow(2,this.csBits)-1;return Ui(a,this.csBits)!==u||a>=this.registry.length?null:this.registry[a]}}],e&&Ti(n.prototype,e),r&&Ti(n,r),Object.defineProperty(n,"prototype",{writable:!1}),t}();function Li(t,n,e){var r,i=1;function o(){var o,a,u=r.length,s=0,l=0,c=0;for(o=0;o=(i=(h+f)/2))?h=i:f=i,r=l,!(l=l[u=+a]))return r[u]=c,t;if(n===(o=+t._x.call(null,l.data)))return c.next=l,r?r[u]=c:t._root=c,t;do{r=r?r[u]=new Array(2):t._root=new Array(2),(a=n>=(i=(h+f)/2))?h=i:f=i}while((u=+a)==(s=+(o>=i)));return r[s]=l,r[u]=c,t}function Bi(t,n,e){this.node=t,this.x0=n,this.x1=e}function $i(t){return t[0]}function Hi(t,n){var e=new Vi(null==n?$i:n,NaN,NaN);return null==t?e:e.addAll(t)}function Vi(t,n,e){this._x=t,this._x0=n,this._x1=e,this._root=void 0}function Xi(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}var Gi=Hi.prototype=Vi.prototype;function Yi(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,a,u,s,l,c,h,f,d=t._root,p={data:r},g=t._x0,y=t._y0,v=t._x1,_=t._y1;if(!d)return t._root=p,t;for(;d.length;)if((l=n>=(o=(g+v)/2))?g=o:v=o,(c=e>=(a=(y+_)/2))?y=a:_=a,i=d,!(d=d[h=c<<1|l]))return i[h]=p,t;if(u=+t._x.call(null,d.data),s=+t._y.call(null,d.data),n===u&&e===s)return p.next=d,i?i[h]=p:t._root=p,t;do{i=i?i[h]=new Array(4):t._root=new Array(4),(l=n>=(o=(g+v)/2))?g=o:v=o,(c=e>=(a=(y+_)/2))?y=a:_=a}while((h=c<<1|l)==(f=(s>=a)<<1|u>=o));return i[f]=d,i[h]=p,t}function Wi(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function Zi(t){return t[0]}function Qi(t){return t[1]}function Ki(t,n,e){var r=new Ji(null==n?Zi:n,null==e?Qi:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Ji(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function to(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}Gi.copy=function(){var t,n,e=new Vi(this._x,this._x0,this._x1),r=this._root;if(!r)return e;if(!r.length)return e._root=Xi(r),e;for(t=[{source:r,target:e._root=new Array(2)}];r=t.pop();)for(var i=0;i<2;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(2)}):r.target[i]=Xi(n));return e},Gi.add=function(t){const n=+this._x.call(null,t);return qi(this.cover(n),n,t)},Gi.addAll=function(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,e=new Float64Array(n);let r=1/0,i=-1/0;for(let o,a=0;ai&&(i=o));if(r>i)return this;this.cover(r).cover(i);for(let r=0;rt||t>=e;)switch(i=+(ts||(i=o.x1)=h))&&(o=l[l.length-1],l[l.length-1]=l[l.length-1-a],l[l.length-1-a]=o)}else{var f=Math.abs(t-+this._x.call(null,c.data));f=(a=(h+f)/2))?h=a:f=a,n=c,!(c=c[s=+u]))return this;if(!c.length)break;n[s+1&1]&&(e=n,l=s)}for(;c.data!==t;)if(r=c,!(c=c.next))return this;return(i=c.next)&&delete c.next,r?(i?r.next=i:delete r.next,this):n?(i?n[s]=i:delete n[s],(c=n[0]||n[1])&&c===(n[1]||n[0])&&!c.length&&(e?e[l]=c:this._root=c),this):(this._root=i,this)},Gi.removeAll=function(t){for(var n=0,e=t.length;n=(a=(m+w)/2))?m=a:w=a,(d=e>=(u=(x+k)/2))?x=u:k=u,(p=r>=(s=(b+M)/2))?b=s:M=s,o=v,!(v=v[g=p<<2|d<<1|f]))return o[g]=_,t;if(l=+t._x.call(null,v.data),c=+t._y.call(null,v.data),h=+t._z.call(null,v.data),n===l&&e===c&&r===h)return _.next=v,o?o[g]=_:t._root=_,t;do{o=o?o[g]=new Array(8):t._root=new Array(8),(f=n>=(a=(m+w)/2))?m=a:w=a,(d=e>=(u=(x+k)/2))?x=u:k=u,(p=r>=(s=(b+M)/2))?b=s:M=s}while((g=p<<2|d<<1|f)==(y=(h>=s)<<2|(c>=u)<<1|l>=a));return o[y]=v,o[g]=_,t}function ro(t,n,e,r,i,o,a){this.node=t,this.x0=n,this.y0=e,this.z0=r,this.x1=i,this.y1=o,this.z1=a}function io(t){return t[0]}function oo(t){return t[1]}function ao(t){return t[2]}function uo(t,n,e,r){var i=new so(null==n?io:n,null==e?oo:e,null==r?ao:r,NaN,NaN,NaN,NaN,NaN,NaN);return null==t?i:i.addAll(t)}function so(t,n,e,r,i,o,a,u,s){this._x=t,this._y=n,this._z=e,this._x0=r,this._y0=i,this._z0=o,this._x1=a,this._y1=u,this._z1=s,this._root=void 0}function lo(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}no.copy=function(){var t,n,e=new Ji(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=to(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=to(n));return e},no.add=function(t){const n=+this._x.call(null,t),e=+this._y.call(null,t);return Yi(this.cover(n,e),n,e,t)},no.addAll=function(t){var n,e,r,i,o=t.length,a=new Array(o),u=new Array(o),s=1/0,l=1/0,c=-1/0,h=-1/0;for(e=0;ec&&(c=r),ih&&(h=i));if(s>c||l>h)return this;for(this.cover(s,l).cover(c,h),e=0;et||t>=i||r>n||n>=o;)switch(u=(nf||(o=s.y0)>d||(a=s.x1)=v)<<1|t>=y)&&(s=p[p.length-1],p[p.length-1]=p[p.length-1-l],p[p.length-1-l]=s)}else{var _=t-+this._x.call(null,g.data),m=n-+this._y.call(null,g.data),x=_*_+m*m;if(x=(u=(p+y)/2))?p=u:y=u,(c=a>=(s=(g+v)/2))?g=s:v=s,n=d,!(d=d[h=c<<1|l]))return this;if(!d.length)break;(n[h+1&3]||n[h+2&3]||n[h+3&3])&&(e=n,f=h)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):n?(i?n[h]=i:delete n[h],(d=n[0]||n[1]||n[2]||n[3])&&d===(n[3]||n[2]||n[1]||n[0])&&!d.length&&(e?e[f]=d:this._root=d),this):(this._root=i,this)},no.removeAll=function(t){for(var n=0,e=t.length;n1&&(v=f.y+f.vy-c.y-c.vy||fo(u)),i>2&&(_=f.z+f.vz-c.z-c.vz||fo(u)),y*=d=((d=Math.sqrt(y*y+v*v+_*_))-e[g])/d*r*n[g],v*=d,_*=d,f.vx-=y*(p=a[g]),i>1&&(f.vy-=v*p),i>2&&(f.vz-=_*p),c.vx+=y*(p=1-p),i>1&&(c.vy+=v*p),i>2&&(c.vz+=_*p)}function d(){if(r){var i,u,l=r.length,c=t.length,h=new Map(r.map(((t,n)=>[s(t,n,r),t])));for(i=0,o=new Array(l);i"function"==typeof t))||Math.random,i=n.find((t=>[1,2,3].includes(t)))||2,d()},f.links=function(n){return arguments.length?(t=n,d(),f):t},f.id=function(t){return arguments.length?(s=t,f):s},f.iterations=function(t){return arguments.length?(h=+t,f):h},f.strength=function(t){return arguments.length?(l="function"==typeof t?t:ho(+t),p(),f):l},f.distance=function(t){return arguments.length?(c="function"==typeof t?t:ho(+t),g(),f):c},f}co.copy=function(){var t,n,e=new so(this._x,this._y,this._z,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1),r=this._root;if(!r)return e;if(!r.length)return e._root=lo(r),e;for(t=[{source:r,target:e._root=new Array(8)}];r=t.pop();)for(var i=0;i<8;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(8)}):r.target[i]=lo(n));return e},co.add=function(t){const n=+this._x.call(null,t),e=+this._y.call(null,t),r=+this._z.call(null,t);return eo(this.cover(n,e,r),n,e,r,t)},co.addAll=function(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,e=new Float64Array(n),r=new Float64Array(n),i=new Float64Array(n);let o=1/0,a=1/0,u=1/0,s=-1/0,l=-1/0,c=-1/0;for(let h,f,d,p,g=0;gs&&(s=f),dl&&(l=d),pc&&(c=p));if(o>s||a>l||u>c)return this;this.cover(o,a,u).cover(s,l,c);for(let o=0;ot||t>=a||i>n||n>=u||o>e||e>=s;)switch(c=(ey||(a=h.y0)>v||(u=h.z0)>_||(s=h.x1)=k)<<2|(n>=w)<<1|t>=b)&&(h=m[m.length-1],m[m.length-1]=m[m.length-1-f],m[m.length-1-f]=h)}else{var M=t-+this._x.call(null,x.data),z=n-+this._y.call(null,x.data),A=e-+this._z.call(null,x.data),S=M*M+z*z+A*A;if(S=(s=(v+x)/2))?v=s:x=s,(f=a>=(l=(_+b)/2))?_=l:b=l,(d=u>=(c=(m+w)/2))?m=c:w=c,n=y,!(y=y[p=d<<2|f<<1|h]))return this;if(!y.length)break;(n[p+1&7]||n[p+2&7]||n[p+3&7]||n[p+4&7]||n[p+5&7]||n[p+6&7]||n[p+7&7])&&(e=n,g=p)}for(;y.data!==t;)if(r=y,!(y=y.next))return this;return(i=y.next)&&delete y.next,r?(i?r.next=i:delete r.next,this):n?(i?n[p]=i:delete n[p],(y=n[0]||n[1]||n[2]||n[3]||n[4]||n[5]||n[6]||n[7])&&y===(n[7]||n[6]||n[5]||n[4]||n[3]||n[2]||n[1]||n[0])&&!y.length&&(e?e[g]=y:this._root=y),this):(this._root=i,this)},co.removeAll=function(t){for(var n=0,e=t.length;n(t=(vo*t+_o)%mo)/mo}();function d(){p(),h.call("tick",e),i1&&(null==c.fy?c.y+=c.vy*=s:(c.y=c.fy,c.vy=0)),r>2&&(null==c.fz?c.z+=c.vz*=s:(c.z=c.fz,c.vz=0));return e}function g(){for(var n,e=0,i=t.length;e1&&isNaN(n.y)||r>2&&isNaN(n.z)){var o=10*(r>2?Math.cbrt(.5+e):r>1?Math.sqrt(.5+e):e),a=e*ko,u=e*Mo;1===r?n.x=o:2===r?(n.x=o*Math.cos(a),n.y=o*Math.sin(a)):(n.x=o*Math.sin(a)*Math.cos(u),n.y=o*Math.cos(a),n.z=o*Math.sin(a)*Math.sin(u))}(isNaN(n.vx)||r>1&&isNaN(n.vy)||r>2&&isNaN(n.vz))&&(n.vx=0,r>1&&(n.vy=0),r>2&&(n.vz=0))}}function y(n){return n.initialize&&n.initialize(t,f,r),n}return null==t&&(t=[]),g(),e={tick:p,restart:function(){return c.restart(d),e},stop:function(){return c.stop(),e},numDimensions:function(t){return arguments.length?(r=Math.min(3,Math.max(1,Math.round(t))),l.forEach(y),e):r},nodes:function(n){return arguments.length?(t=n,g(),l.forEach(y),e):t},alpha:function(t){return arguments.length?(i=+t,e):i},alphaMin:function(t){return arguments.length?(o=+t,e):o},alphaDecay:function(t){return arguments.length?(a=+t,e):+a},alphaTarget:function(t){return arguments.length?(u=+t,e):u},velocityDecay:function(t){return arguments.length?(s=1-t,e):1-s},randomSource:function(t){return arguments.length?(f=t,l.forEach(y),e):f},force:function(t,n){return arguments.length>1?(null==n?l.delete(t):l.set(t,y(n)),e):l.get(t)},find:function(){var n,e,i,o,a,u,s=Array.prototype.slice.call(arguments),l=s.shift()||0,c=(r>1?s.shift():null)||0,h=(r>2?s.shift():null)||0,f=s.shift()||1/0,d=0,p=t.length;for(f*=f,d=0;d1?(h.on(t,n),e):h.on(t)}}}function Ao(){var t,n,e,r,i,o,a=ho(-30),u=1,s=1/0,l=.81;function c(r){var o,a=t.length,u=(1===n?Hi(t,xo):2===n?Ki(t,xo,bo):3===n?uo(t,xo,bo,wo):null).visitAfter(f);for(i=r,o=0;o1&&(t.y=a/c),n>2&&(t.z=u/c)}else{(e=t).x=e.data.x,n>1&&(e.y=e.data.y),n>2&&(e.z=e.data.z);do{l+=o[e.data.index]}while(e=e.next)}t.value=l}function d(t,a,c,h,f){if(!t.value)return!0;var d=[c,h,f][n-1],p=t.x-e.x,g=n>1?t.y-e.y:0,y=n>2?t.z-e.z:0,v=d-a,_=p*p+g*g+y*y;if(v*v/l<_)return _1&&0===g&&(_+=(g=fo(r))*g),n>2&&0===y&&(_+=(y=fo(r))*y),_1&&(e.vy+=g*t.value*i/_),n>2&&(e.vz+=y*t.value*i/_)),!0;if(!(t.length||_>=s)){(t.data!==e||t.next)&&(0===p&&(_+=(p=fo(r))*p),n>1&&0===g&&(_+=(g=fo(r))*g),n>2&&0===y&&(_+=(y=fo(r))*y),_1&&(e.vy+=g*v),n>2&&(e.vz+=y*v))}while(t=t.next)}}return c.initialize=function(e,...i){t=e,r=i.find((t=>"function"==typeof t))||Math.random,n=i.find((t=>[1,2,3].includes(t)))||2,h()},c.strength=function(t){return arguments.length?(a="function"==typeof t?t:ho(+t),h(),c):a},c.distanceMin=function(t){return arguments.length?(u=t*t,c):Math.sqrt(u)},c.distanceMax=function(t){return arguments.length?(s=t*t,c):Math.sqrt(s)},c.theta=function(t){return arguments.length?(l=t*t,c):Math.sqrt(l)},c}const{abs:So,cos:Co,sin:Eo,acos:Oo,atan2:No,sqrt:Po,pow:jo}=Math;function To(t){return t<0?-jo(-t,1/3):jo(t,1/3)}const Ro=Math.PI,Do=2*Ro,Io=Ro/2,Uo=Number.MAX_SAFE_INTEGER||9007199254740991,Fo=Number.MIN_SAFE_INTEGER||-9007199254740991,Lo={x:0,y:0,z:0},qo={Tvalues:[-.06405689286260563,.06405689286260563,-.1911188674736163,.1911188674736163,-.3150426796961634,.3150426796961634,-.4337935076260451,.4337935076260451,-.5454214713888396,.5454214713888396,-.6480936519369755,.6480936519369755,-.7401241915785544,.7401241915785544,-.820001985973903,.820001985973903,-.8864155270044011,.8864155270044011,-.9382745520027328,.9382745520027328,-.9747285559713095,.9747285559713095,-.9951872199970213,.9951872199970213],Cvalues:[.12793819534675216,.12793819534675216,.1258374563468283,.1258374563468283,.12167047292780339,.12167047292780339,.1155056680537256,.1155056680537256,.10744427011596563,.10744427011596563,.09761865210411388,.09761865210411388,.08619016153195327,.08619016153195327,.0733464814110803,.0733464814110803,.05929858491543678,.05929858491543678,.04427743881741981,.04427743881741981,.028531388628933663,.028531388628933663,.0123412297999872,.0123412297999872],arcfn:function(t,n){const e=n(t);let r=e.x*e.x+e.y*e.y;return void 0!==e.z&&(r+=e.z*e.z),Po(r)},compute:function(t,n,e){if(0===t)return n[0].t=0,n[0];const r=n.length-1;if(1===t)return n[r].t=1,n[r];const i=1-t;let o=n;if(0===r)return n[0].t=t,n[0];if(1===r){const n={x:i*o[0].x+t*o[1].x,y:i*o[0].y+t*o[1].y,t:t};return e&&(n.z=i*o[0].z+t*o[1].z),n}if(r<4){let n,a,u,s=i*i,l=t*t,c=0;2===r?(o=[o[0],o[1],o[2],Lo],n=s,a=i*t*2,u=l):3===r&&(n=s*i,a=s*t*3,u=i*l*3,c=t*l);const h={x:n*o[0].x+a*o[1].x+u*o[2].x+c*o[3].x,y:n*o[0].y+a*o[1].y+u*o[2].y+c*o[3].y,t:t};return e&&(h.z=n*o[0].z+a*o[1].z+u*o[2].z+c*o[3].z),h}const a=JSON.parse(JSON.stringify(n));for(;a.length>1;){for(let n=0;n1;i--,o--){const t=[];for(let e,i=0;io.x.min&&(n=o.x.min),e>o.y.min&&(e=o.y.min),r0&&(a.c1=n,a.c2=r,a.s1=t,a.s2=e,o.push(a))}))})),o},makeshape:function(t,n,e){const r=n.points.length,i=t.points.length,o=qo.makeline(n.points[r-1],t.points[0]),a=qo.makeline(t.points[i-1],n.points[0]),u={startcap:o,forward:t,back:n,endcap:a,bbox:qo.findbbox([o,t,n,a]),intersections:function(t){return qo.shapeintersections(u,u.bbox,t,t.bbox,e)}};return u},getminmax:function(t,n,e){if(!e)return{min:0,max:0};let r,i,o=Uo,a=Fo;-1===e.indexOf(0)&&(e=[0].concat(e)),-1===e.indexOf(1)&&e.push(1);for(let u=0,s=e.length;ua&&(a=i[n]);return{min:o,mid:(o+a)/2,max:a,size:a-o}},align:function(t,n){const e=n.p1.x,r=n.p1.y,i=-No(n.p2.y-r,n.p2.x-e);return t.map((function(t){return{x:(t.x-e)*Co(i)-(t.y-r)*Eo(i),y:(t.x-e)*Eo(i)+(t.y-r)*Co(i)}}))},roots:function(t,n){n=n||{p1:{x:0,y:0},p2:{x:1,y:0}};const e=t.length-1,r=qo.align(t,n),i=function(t){return 0<=t&&t<=1};if(2===e){const t=r[0].y,n=r[1].y,e=r[2].y,o=t-2*n+e;if(0!==o){const r=-Po(n*n-t*e),a=-t+n;return[-(r+a)/o,-(-r+a)/o].filter(i)}return n!==e&&0===o?[(2*n-e)/(2*n-2*e)].filter(i):[]}const o=r[0].y,a=r[1].y,u=r[2].y;let s=3*a-o-3*u+r[3].y,l=3*o-6*a+3*u,c=-3*o+3*a,h=o;if(qo.approximately(s,0)){if(qo.approximately(l,0))return qo.approximately(c,0)?[]:[-h/c].filter(i);const t=Po(c*c-4*l*h),n=2*l;return[(t-c)/n,(-c-t)/n].filter(i)}l/=s,c/=s,h/=s;const f=(3*c-l*l)/3,d=f/3,p=(2*l*l*l-9*l*c+27*h)/27,g=p/2,y=g*g+d*d*d;let v,_,m,x,b;if(y<0){const t=-f/3,n=Po(t*t*t),e=-p/(2*n),r=Oo(e<-1?-1:e>1?1:e),o=2*To(n);return m=o*Co(r/3)-l/3,x=o*Co((r+Do)/3)-l/3,b=o*Co((r+2*Do)/3)-l/3,[m,x,b].filter(i)}if(0===y)return v=g<0?To(-g):-To(g),m=2*v-l/3,x=-v-l/3,[m,x].filter(i);{const t=Po(y);return v=To(-g+t),_=To(g+t),[v-_-l/3].filter(i)}},droots:function(t){if(3===t.length){const n=t[0],e=t[1],r=t[2],i=n-2*e+r;if(0!==i){const t=-Po(e*e-n*r),o=-n+e;return[-(t+o)/i,-(-t+o)/i]}return e!==r&&0===i?[(2*e-r)/(2*(e-r))]:[]}if(2===t.length){const n=t[0],e=t[1];return n!==e?[n/(n-e)]:[]}return[]},curvature:function(t,n,e,r,i){let o,a,u,s,l=0,c=0;const h=qo.compute(t,n),f=qo.compute(t,e),d=h.x*h.x+h.y*h.y;if(r?(o=Po(jo(h.y*f.z-f.y*h.z,2)+jo(h.z*f.x-f.z*h.x,2)+jo(h.x*f.y-f.x*h.y,2)),a=jo(d+h.z*h.z,1.5)):(o=h.x*f.y-h.y*f.x,a=jo(d,1.5)),0===o||0===a)return{k:0,r:0};if(l=o/a,c=a/o,!i){const i=qo.curvature(t-.001,n,e,r,!0).k,o=qo.curvature(t+.001,n,e,r,!0).k;s=(o-l+(l-i))/2,u=(So(o-l)+So(l-i))/2}return{k:l,r:c,dk:s,adk:u}},inflections:function(t){if(t.length<4)return[];const n=qo.align(t,{p1:t[0],p2:t.slice(-1)[0]}),e=n[2].x*n[1].y,r=n[3].x*n[1].y,i=n[1].x*n[2].y,o=18*(-3*e+2*r+3*i-n[3].x*n[2].y),a=18*(3*e-r-3*i),u=18*(i-e);if(qo.approximately(o,0)){if(!qo.approximately(a,0)){let t=-u/a;if(0<=t&&t<=1)return[t]}return[]}const s=2*o;if(qo.approximately(s,0))return[];const l=a*a-4*o*u;if(l<0)return[];const c=Math.sqrt(l);return[(c-a)/s,-(a+c)/s].filter((function(t){return 0<=t&&t<=1}))},bboxoverlap:function(t,n){const e=["x","y"],r=e.length;for(let i,o,a,u,s=0;s=u)return!1;return!0},expandbox:function(t,n){n.x.mint.x.max&&(t.x.max=n.x.max),n.y.max>t.y.max&&(t.y.max=n.y.max),n.z&&n.z.max>t.z.max&&(t.z.max=n.z.max),t.x.mid=(t.x.min+t.x.max)/2,t.y.mid=(t.y.min+t.y.max)/2,t.z&&(t.z.mid=(t.z.min+t.z.max)/2),t.x.size=t.x.max-t.x.min,t.y.size=t.y.max-t.y.min,t.z&&(t.z.size=t.z.max-t.z.min)},pairiteration:function(t,n,e){const r=t.bbox(),i=n.bbox(),o=1e5,a=e||.5;if(r.x.size+r.y.sizek||k>M)&&(w+=Do),w>M&&(b=M,M=w,w=b)):M4){if(1!==arguments.length)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");r=!0}}else if(6!==i&&8!==i&&9!==i&&12!==i&&1!==arguments.length)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");const o=this._3d=!r&&(9===i||12===i)||t&&t[0]&&void 0!==t[0].z,a=this.points=[];for(let t=0,e=o?3:2;tt+$o(n.y)),0)0}length(){return qo.length(this.derivative.bind(this))}static getABC(t=2,n,e,r,i=.5){const o=qo.projectionratio(i,t),a=1-o,u={x:o*n.x+a*r.x,y:o*n.y+a*r.y},s=qo.abcratio(i,t);return{A:{x:e.x+(e.x-u.x)/s,y:e.y+(e.y-u.y)/s},B:e,C:u,S:n,E:r}}getABC(t,n){n=n||this.get(t);let e=this.points[0],r=this.points[this.order];return Qo.getABC(this.order,e,n,r,t)}getLUT(t){if(this.verify(),t=t||100,this._lut.length===t+1)return this._lut;this._lut=[],t++,this._lut=[];for(let n,e,r=0;r1?1:h,s=this.compute(h),s.t=h,s.d=l,s}get(t){return this.compute(t)}point(t){return this.points[t]}compute(t){return this.ratios?qo.computeWithRatios(t,this.points,this.ratios,this._3d):qo.compute(t,this.points,this._3d,this.ratios)}raise(){const t=this.points,n=[t[0]],e=t.length;for(let r,i,o=1;o1;){e=[];for(let o,a=0,u=n.length-1;a=0&&t<=1})),n=n.concat(t[e].sort(qo.numberSort))}.bind(this)),t.values=n.sort(qo.numberSort).filter((function(t,e){return n.indexOf(t)===e})),t}bbox(){const t=this.extrema(),n={};return this.dims.forEach(function(e){n[e]=qo.getminmax(this,e,t[e])}.bind(this)),n}overlaps(t){const n=this.bbox(),e=t.bbox();return qo.bboxoverlap(n,e)}offset(t,n){if(void 0!==n){const e=this.get(t),r=this.normal(t),i={c:e,n:r,x:e.x+r.x*n,y:e.y+r.y*n};return this._3d&&(i.z=e.z+r.z*n),i}if(this._linear){const n=this.normal(0),e=this.points.map((function(e){const r={x:e.x+t*n.x,y:e.y+t*n.y};return e.z&&n.z&&(r.z=e.z+t*n.z),r}));return[new Qo(e)]}return this.reduce().map((function(n){return n._linear?n.offset(t)[0]:n.scale(t)}))}simple(){if(3===this.order){const t=qo.angle(this.points[0],this.points[3],this.points[1]),n=qo.angle(this.points[0],this.points[3],this.points[2]);if(t>0&&n<0||t<0&&n>0)return!1}const t=this.normal(0),n=this.normal(1);let e=t.x*n.x+t.y*n.y;return this._3d&&(e+=t.z*n.z),$o(Yo(e))(1-i/r)*n+i/r*e));return new Qo(this.points.map(((n,e)=>({x:n.x+t.x*i[e],y:n.y+t.y*i[e]}))))}scale(t){const n=this.order;let e=!1;if("function"==typeof t&&(e=t),e&&2===n)return this.raise().scale(e);const r=this.clockwise,i=this.points;if(this._linear)return this.translate(this.normal(0),e?e(0):t,e?e(1):t);const o=e?e(0):t,a=e?e(1):t,u=[this.offset(0,10),this.offset(1,10)],s=[],l=qo.lli4(u[0],u[0].c,u[1],u[1].c);if(!l)throw new Error("cannot scale this curve. Try reducing it first.");return[0,1].forEach((function(t){const e=s[t*n]=qo.copy(i[t*n]);e.x+=(t?a:o)*u[t].n.x,e.y+=(t?a:o)*u[t].n.y})),e?([0,1].forEach((function(o){if(2!==n||!o){var a=i[o+1],u={x:a.x-l.x,y:a.y-l.y},c=e?e((o+1)/n):t;e&&!r&&(c=-c);var h=Wo(u.x*u.x+u.y*u.y);u.x/=h,u.y/=h,s[o+1]={x:a.x+c*u.x,y:a.y+c*u.y}}})),new Qo(s)):([0,1].forEach((t=>{if(2===n&&t)return;const e=s[t*n],r=this.derivative(t),o={x:e.x+r.x,y:e.y+r.y};s[t+1]=qo.lli4(e,o,l,i[t+1])})),new Qo(s))}outline(t,n,e,r){if(n=void 0===n?t:n,this._linear){const i=this.normal(0),o=this.points[0],a=this.points[this.points.length-1];let u,s,l;void 0===e&&(e=t,r=n),u={x:o.x+i.x*t,y:o.y+i.y*t},l={x:a.x+i.x*e,y:a.y+i.y*e},s={x:(u.x+l.x)/2,y:(u.y+l.y)/2};const c=[u,s,l];u={x:o.x-i.x*n,y:o.y-i.y*n},l={x:a.x-i.x*r,y:a.y-i.y*r},s={x:(u.x+l.x)/2,y:(u.y+l.y)/2};const h=[l,s,u],f=qo.makeline(h[2],c[0]),d=qo.makeline(c[2],h[0]),p=[f,new Qo(c),d,new Qo(h)];return new Bo(p)}const i=this.reduce(),o=i.length,a=[];let u,s=[],l=0,c=this.length();const h=void 0!==e&&void 0!==r;function f(t,n,e,r,i){return function(o){const a=r/e,u=(r+i)/e,s=n-t;return qo.map(o,0,1,t+a*s,t+u*s)}}i.forEach((function(i){const o=i.length();h?(a.push(i.scale(f(t,e,c,l,o))),s.push(i.scale(f(-n,-r,c,l,o)))):(a.push(i.scale(t)),s.push(i.scale(-n))),l+=o})),s=s.map((function(t){return u=t.points,u[3]?t.points=[u[3],u[2],u[1],u[0]]:t.points=[u[2],u[1],u[0]],t})).reverse();const d=a[0].points[0],p=a[o-1].points[a[o-1].points.length-1],g=s[o-1].points[s[o-1].points.length-1],y=s[0].points[0],v=qo.makeline(g,d),_=qo.makeline(p,y),m=[v].concat(a).concat([_]).concat(s);return new Bo(m)}outlineshapes(t,n,e){n=n||t;const r=this.outline(t,n).curves,i=[];for(let t=1,n=r.length;t1,o.endcap.virtual=t{var o=this.get(t);return qo.between(o.x,n,r)&&qo.between(o.y,e,i)}))}selfintersects(t){const n=this.reduce(),e=n.length-2,r=[];for(let i,o,a,u=0;u0&&(i=i.concat(n))})),i}arcs(t){return t=t||.5,this._iterate(t,[])}_error(t,n,e,r){const i=(r-e)/4,o=this.get(e+i),a=this.get(r-i),u=qo.dist(t,n),s=qo.dist(t,o),l=qo.dist(t,a);return $o(s-u)+$o(l-u)}_iterate(t,n){let e,r=0,i=1;do{e=0,i=1;let o,a,u,s,l,c=this.get(r),h=!1,f=!1,d=i,p=1;do{if(f=h,s=u,d=(r+i)/2,o=this.get(d),a=this.get(i),u=qo.getccenter(c,o,a),u.interval={start:r,end:i},h=this._error(u,c,r,i)<=t,l=f&&!h,l||(p=i),h){if(i>=1){if(u.interval.end=p=1,s=u,i>1){let t={x:u.x+u.r*Xo(u.e),y:u.y+u.r*Go(u.e)};u.e+=qo.angle({x:u.x,y:u.y},t,this.get(1))}break}i+=(i-r)/2}else i=d}while(!l&&e++<100);if(e>=100)break;s=s||u,n.push(s),r=p}while(i<1);return n}}function Ko(t,n){if(null==t)return{};var e,r,i=function(t,n){if(null==t)return{};var e,r,i={},o=Object.keys(t);for(r=0;r=0||(i[e]=t[e]);return i}(t,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,e)&&(i[e]=t[e])}return i}function Jo(t,n){return function(t){if(Array.isArray(t))return t}(t)||function(t,n){var e=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=e){var r,i,o,a,u=[],s=!0,l=!1;try{if(o=(e=e.call(t)).next,0===n){if(Object(e)!==e)return;s=!1}else for(;!(s=(r=o.call(e)).done)&&(u.push(r.value),u.length!==n);s=!0);}catch(t){l=!0,i=t}finally{try{if(!s&&null!=e.return&&(a=e.return(),Object(a)!==a))return}finally{if(l)throw i}}return u}}(t,n)||na(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function ta(t){return function(t){if(Array.isArray(t))return ea(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||na(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function na(t,n){if(t){if("string"==typeof t)return ea(t,n);var e=Object.prototype.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?ea(t,n):void 0}}function ea(t,n){(null==n||n>t.length)&&(n=t.length);for(var e=0,r=new Array(n);et.cooldownTicks||new Date-t.startTickTime>t.cooldownTime||t.d3AlphaMin>0&&t.forceLayout.alpha()0){var a=Math.atan2(r.y-e.y,r.x-e.x),u=i*n,s={x:(e.x+r.x)/2+u*Math.cos(a-Math.PI/2),y:(e.y+r.y)/2+u*Math.sin(a-Math.PI/2)};t.__controlPoints=[s.x,s.y]}else{var l=70*n;t.__controlPoints=[r.x,r.y-l,r.x+l,r.y]}}));var f=[],d=[],p=h;if(t.linkCanvasObject){var g=[],y=[];h.forEach((function(t){return({before:f,after:d,replace:g}[a(t)]||y).push(t)})),p=[].concat(s(f),d,y),f=f.concat(g)}l.save(),f.forEach((function(n){return t.linkCanvasObject(n,l,t.globalScale)})),l.restore();var v=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],e=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],i=(n instanceof Array?n.length?n:[void 0]:[n]).map((function(t){return{keyAccessor:t,isProp:!(t instanceof Function)}})),o=t.reduce((function(t,n){var r=t,o=n;return i.forEach((function(t,n){var a,u=t.keyAccessor;if(t.isProp){var s=o,l=s[u],c=Ko(s,[u].map(ra));a=l,o=c}else a=u(o,n);n+11&&void 0!==arguments[1]?arguments[1]:1;r===i.length?Object.keys(n).forEach((function(t){return n[t]=e(n[t])})):Object.values(n).forEach((function(n){return t(n,r+1)}))}(o);var a=o;return r&&(a=[],function t(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];e.length===i.length?a.push({keys:e,vals:n}):Object.entries(n).forEach((function(n){var r=Jo(n,2),i=r[0],o=r[1];return t(o,[].concat(ta(e),[i]))}))}(o),n instanceof Array&&0===n.length&&1===a.length&&(a[0].keys=[])),a}(p,[e,r,i]);l.save(),Object.entries(v).forEach((function(n){var e=u(n,2),r=e[0],o=e[1],a=r&&"undefined"!==r?r:"rgba(0,0,0,0.15)";Object.entries(o).forEach((function(n){var e=u(n,2),r=e[0],o=e[1],h=(r||1)/t.globalScale+c;Object.entries(o).forEach((function(t){var n=u(t,2);n[0];var e=n[1],r=i(e[0]);l.beginPath(),e.forEach((function(t){var n=t.source,e=t.target;if(n&&e&&n.hasOwnProperty("x")&&e.hasOwnProperty("x")){l.moveTo(n.x,n.y);var r=t.__controlPoints;r?l[2===r.length?"quadraticCurveTo":"bezierCurveTo"].apply(l,s(r).concat([e.x,e.y])):l.lineTo(e.x,e.y)}})),l.strokeStyle=a,l.lineWidth=h,l.setLineDash(r||[]),l.stroke()}))}))})),l.restore(),l.save(),d.forEach((function(n){return t.linkCanvasObject(n,l,t.globalScale)})),l.restore()}(),!t.isShadow&&(n=Kr(t.linkDirectionalArrowLength),e=Kr(t.linkDirectionalArrowRelPos),r=Kr(t.linkVisibility),i=Kr(t.linkDirectionalArrowColor||t.linkColor),o=Kr(t.nodeVal),(l=t.ctx).save(),t.graphData.links.filter(r).forEach((function(r){var u=n(r);if(u&&!(u<0)){var c=r.source,h=r.target;if(c&&h&&c.hasOwnProperty("x")&&h.hasOwnProperty("x")){var f=Math.sqrt(Math.max(0,o(c)||1))*t.nodeRelSize,d=Math.sqrt(Math.max(0,o(h)||1))*t.nodeRelSize,p=Math.min(1,Math.max(0,e(r))),g=i(r)||"rgba(0,0,0,0.28)",y=u/1.6/2,v=r.__controlPoints&&a(Qo,[c.x,c.y].concat(s(r.__controlPoints),[h.x,h.y])),_=v?function(t){return v.get(t)}:function(t){return{x:c.x+(h.x-c.x)*t||0,y:c.y+(h.y-c.y)*t||0}},m=v?v.length():Math.sqrt(Math.pow(h.x-c.x,2)+Math.pow(h.y-c.y,2)),x=f+u+(m-f-d-u)*p,b=_(x/m),w=_((x-u)/m),k=_((x-.8*u)/m),M=Math.atan2(b.y-w.y,b.x-w.x)-Math.PI/2;l.beginPath(),l.moveTo(b.x,b.y),l.lineTo(w.x+y*Math.cos(M),w.y+y*Math.sin(M)),l.lineTo(k.x,k.y),l.lineTo(w.x-y*Math.cos(M),w.y-y*Math.sin(M)),l.fillStyle=g,l.fill()}}})),l.restore()),!t.isShadow&&function(){var n=Kr(t.linkDirectionalParticles),e=Kr(t.linkDirectionalParticleSpeed),r=Kr(t.linkDirectionalParticleWidth),i=Kr(t.linkVisibility),o=Kr(t.linkDirectionalParticleColor||t.linkColor),u=t.ctx;u.save(),t.graphData.links.filter(i).forEach((function(i){var l=n(i);if(i.hasOwnProperty("__photons")&&i.__photons.length){var c=i.source,h=i.target;if(c&&h&&c.hasOwnProperty("x")&&h.hasOwnProperty("x")){var f=e(i),d=i.__photons||[],p=Math.max(0,r(i)/2)/Math.sqrt(t.globalScale),g=o(i)||"rgba(0,0,0,0.28)";u.fillStyle=g;var y=i.__controlPoints?a(Qo,[c.x,c.y].concat(s(i.__controlPoints),[h.x,h.y])):null,v=0,_=!1;d.forEach((function(t){var n=!!t.__singleHop;if(t.hasOwnProperty("__progressRatio")||(t.__progressRatio=n?0:v/l),!n&&v++,t.__progressRatio+=f,t.__progressRatio>=1){if(n)return void(_=!0);t.__progressRatio=t.__progressRatio%1}var e=t.__progressRatio,r=y?y.get(e):{x:c.x+(h.x-c.x)*e||0,y:c.y+(h.y-c.y)*e||0};u.beginPath(),u.arc(r.x,r.y,p,0,2*Math.PI,!1),u.fill()})),_&&(i.__photons=i.__photons.filter((function(t){return!t.__singleHop||t.__progressRatio<=1})))}}})),u.restore()}(),function(){var n=Kr(t.nodeVisibility),e=Kr(t.nodeVal),r=Kr(t.nodeColor),i=Kr(t.nodeCanvasObjectMode),o=t.ctx,a=t.isShadow/t.globalScale,u=t.graphData.nodes.filter(n);o.save(),u.forEach((function(n){var u=i(n);if(!t.nodeCanvasObject||"before"!==u&&"replace"!==u||(t.nodeCanvasObject(n,o,t.globalScale),"replace"!==u)){var s=Math.sqrt(Math.max(0,e(n)||1))*t.nodeRelSize+a;o.beginPath(),o.arc(n.x,n.y,s,0,2*Math.PI,!1),o.fillStyle=r(n)||"rgba(31, 120, 180, 0.92)",o.fill(),t.nodeCanvasObject&&"after"===u&&t.nodeCanvasObject(n,t.ctx,t.globalScale)}else o.restore()})),o.restore()}(),this},emitParticle:function(t,n){return n&&(!n.__photons&&(n.__photons=[]),n.__photons.push({__singleHop:!0})),this}},stateInit:function(){return{forceLayout:zo().force("link",yo()).force("charge",Ao()).force("center",Li()).force("dagRadial",null).stop(),engineRunning:!1}},init:function(t,n){n.ctx=t},update:function(t){t.engineRunning=!1,t.onUpdate(),null!==t.nodeAutoColorBy&&sa(t.graphData.nodes,Kr(t.nodeAutoColorBy),t.nodeColor),null!==t.linkAutoColorBy&&sa(t.graphData.links,Kr(t.linkAutoColorBy),t.linkColor),t.graphData.links.forEach((function(n){n.source=n[t.linkSource],n.target=n[t.linkTarget]})),t.forceLayout.stop().alpha(1).nodes(t.graphData.nodes);var n=t.forceLayout.force("link");n&&n.id((function(n){return n[t.nodeId]})).links(t.graphData.links);var e=t.dagMode&&function(t,n){var e=t.nodes,o=t.links,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},l=a.nodeFilter,c=void 0===l?function(){return!0}:l,h=a.onLoopError,f=void 0===h?function(t){throw"Invalid DAG structure! Found cycle in node path: ".concat(t.join(" -> "),".")}:h,d={};e.forEach((function(t){return d[n(t)]={data:t,out:[],depth:-1,skip:!c(t)}})),o.forEach((function(t){var e=t.source,i=t.target,o=l(e),a=l(i);if(!d.hasOwnProperty(o))throw"Missing source node with id: ".concat(o);if(!d.hasOwnProperty(a))throw"Missing target node with id: ".concat(a);var u=d[o],s=d[a];function l(t){return"object"===r(t)?n(t):t}u.out.push(s)}));var p=[];return function t(e){for(var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=function(){var o=e[a];if(-1!==r.indexOf(o)){var u=[].concat(s(r.slice(r.indexOf(o))),[o]).map((function(t){return n(t.data)}));return p.some((function(t){return t.length===u.length&&t.every((function(t,n){return t===u[n]}))}))||(p.push(u),f(u)),1}i>o.depth&&(o.depth=i,t(o.out,[].concat(s(r),[o]),i+(o.skip?0:1)))},a=0,u=e.length;a1&&(c.vy+=f*g),o>2&&(c.vz+=d*g)}}function c(){if(i){var n,e=i.length;for(a=new Array(e),u=new Array(e),n=0;n[1,2,3].includes(t)))||2,c()},l.strength=function(t){return arguments.length?(s="function"==typeof t?t:ho(+t),c(),l):s},l.radius=function(n){return arguments.length?(t="function"==typeof n?n:ho(+n),c(),l):t},l.x=function(t){return arguments.length?(n=+t,l):n},l.y=function(t){return arguments.length?(e=+t,l):e},l.z=function(t){return arguments.length?(r=+t,l):r},l}((function(n){var r=e[n[t.nodeId]]||-1;return("radialin"===t.dagMode?o-r:r)*a})).strength((function(n){return t.dagNodeFilter(n)?1:0})):null);for(var f=0;f0&&t.forceLayout.alpha()1?r-1:0),o=1;o1&&void 0!==arguments[1]?arguments[1]:0,e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,r=arguments.length,i=new Array(r>3?r-3:0),o=3;o1&&void 0!==arguments[1]?arguments[1]:function(){return!0},e=Kr(t.nodeVal),r=function(n){return Math.sqrt(Math.max(0,e(n)||1))*t.nodeRelSize},i=t.graphData.nodes.filter(n).map((function(t){return{x:t.x,y:t.y,r:r(t)}}));return i.length?{x:[ur(i,(function(t){return t.x-t.r})),ar(i,(function(t){return t.x+t.r}))],y:[ur(i,(function(t){return t.y-t.r})),ar(i,(function(t){return t.y+t.r}))]}:null},pauseAnimation:function(t){return t.animationFrameRequestId&&(cancelAnimationFrame(t.animationFrameRequestId),t.animationFrameRequestId=null),this},resumeAnimation:function(t){return t.animationFrameRequestId||this._animationCycle(),this},_destructor:function(){this.pauseAnimation(),this.graphData({nodes:[],links:[]})}},ya),stateInit:function(){return{lastSetZoom:1,zoom:er(),forceGraph:new ha,shadowGraph:(new ha).cooldownTicks(0).nodeColor("__indexColor").linkColor("__indexColor").isShadow(!0),colorTracker:new Fi}},init:function(t,n){var r=this;t.innerHTML="";var i=document.createElement("div");i.classList.add("force-graph-container"),i.style.position="relative",t.appendChild(i),n.canvas=document.createElement("canvas"),n.backgroundColor&&(n.canvas.style.background=n.backgroundColor),i.appendChild(n.canvas),n.shadowCanvas=document.createElement("canvas");var o=n.canvas.getContext("2d"),a=n.shadowCanvas.getContext("2d",{willReadFrequently:!0}),u={x:-1e12,y:-1e12},s=function(){var t=null,e=window.devicePixelRatio,r=u.x>0&&u.y>0?a.getImageData(u.x*e,u.y*e,1,1):null;return r&&(t=n.colorTracker.lookup(r.data)),t};kt(n.canvas).call(function(){var t,n,e,r,i=Ut,o=Ft,a=Lt,u=qt,s={},l=At("start","drag","end"),c=0,h=0;function f(t){t.on("mousedown.drag",d).filter(u).on("touchstart.drag",y).on("touchmove.drag",v,Ot).on("touchend.drag touchcancel.drag",_).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(a,u){if(!r&&i.call(this,a,u)){var s=m(this,o.call(this,a,u),a,u,"mouse");s&&(kt(a.view).on("mousemove.drag",p,Nt).on("mouseup.drag",g,Nt),Tt(a.view),Pt(a),e=!1,t=a.clientX,n=a.clientY,s("start",a))}}function p(r){if(jt(r),!e){var i=r.clientX-t,o=r.clientY-n;e=i*i+o*o>h}s.mouse("drag",r)}function g(t){kt(t.view).on("mousemove.drag mouseup.drag",null),Rt(t.view,e),jt(t),s.mouse("end",t)}function y(t,n){if(i.call(this,t,n)){var e,r,a=t.changedTouches,u=o.call(this,t,n),s=a.length;for(e=0;e0||n.isPointerPressed)&&("touch"!==e.pointerType||void 0===e.movementX||[e.movementX,e.movementY].some((function(t){return Math.abs(t)>1})))&&(n.isPointerDragging=!0);var r,o,a,s=(r=i.getBoundingClientRect(),o=window.pageXOffset||document.documentElement.scrollLeft,a=window.pageYOffset||document.documentElement.scrollTop,{top:r.top+a,left:r.left+o});u.x=e.pageX-s.left,u.y=e.pageY-s.top,l.style.top="".concat(u.y,"px"),l.style.left="".concat(u.x,"px"),l.style.transform="translate(-".concat(u.x/n.width*100,"%, ").concat(n.height-u.y<100?"calc(-100% - 8px)":"21px",")")}),{passive:!0})})),i.addEventListener("pointerup",(function(t){if(n.isPointerPressed=!1,n.isPointerDragging)n.isPointerDragging=!1;else{var e=[t,n.pointerDownEvent];requestAnimationFrame((function(){if(0===t.button)if(n.hoverObj){var r=n["on".concat(n.hoverObj.type,"Click")];r&&r.apply(void 0,[n.hoverObj.d].concat(e))}else n.onBackgroundClick&&n.onBackgroundClick.apply(n,e);if(2===t.button)if(n.hoverObj){var i=n["on".concat(n.hoverObj.type,"RightClick")];i&&i.apply(void 0,[n.hoverObj.d].concat(e))}else n.onBackgroundRightClick&&n.onBackgroundRightClick.apply(n,e)}))}}),{passive:!0}),i.addEventListener("contextmenu",(function(t){return!(n.onBackgroundRightClick||n.onNodeRightClick||n.onLinkRightClick)||(t.preventDefault(),!1)})),n.forceGraph(o),n.shadowGraph(a);var c=function(t,n,e){var r=!0,i=!0;if("function"!=typeof t)throw new TypeError("Expected a function");return zr(e)&&(r="leading"in e?!!e.leading:r,i="trailing"in e?!!e.trailing:i),Dr(t,n,{leading:r,maxWait:n,trailing:i})}((function(){ma(a,n.width,n.height),n.shadowGraph.linkWidth((function(t){return Kr(n.linkWidth)(t)+n.linkHoverPrecision}));var t=Ge(n.canvas);n.shadowGraph.globalScale(t.k).tickFrame()}),800);n.flushShadowCanvas=c.flush,(this._animationCycle=function t(){var e=!n.autoPauseRedraw||!!n.needsRedraw||n.forceGraph.isEngineRunning()||n.graphData.links.some((function(t){return t.__photons&&t.__photons.length}));if(n.needsRedraw=!1,n.enablePointerInteraction){var r=n.isPointerDragging?null:s();if(r!==n.hoverObj){var i=n.hoverObj,a=i?i.type:null,u=r?r.type:null;if(a&&a!==u){var h=n["on".concat(a,"Hover")];h&&h(null,i.d)}if(u){var f=n["on".concat(u,"Hover")];f&&f(r.d,a===u?i.d:null)}var d=r&&Kr(n["".concat(r.type.toLowerCase(),"Label")])(r.d)||"";l.style.visibility=d?"visible":"hidden",l.innerHTML=d,n.canvas.classList[r&&n["on".concat(u,"Click")]||!r&&n.onBackgroundClick?"add":"remove"]("clickable"),n.hoverObj=r}e&&c()}if(e){ma(o,n.width,n.height);var p=Ge(n.canvas).k;n.onRenderFramePre&&n.onRenderFramePre(o,p),n.forceGraph.globalScale(p).tickFrame(),n.onRenderFramePost&&n.onRenderFramePost(o,p)}Vr(),n.animationFrameRequestId=requestAnimationFrame(t)})()},update:function(t){}});return xa})); diff --git a/hal-core/resources/web/js/lib/jquery-1.11.3.min.js b/hal-core/resources/web/js/lib/jquery-1.11.3.min.js deleted file mode 100644 index 0f60b7bd..00000000 --- a/hal-core/resources/web/js/lib/jquery-1.11.3.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; - -return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m(""); + + // Init form settings + var form = jQuery("#AjaxFileUpload"); + //form.attr("encoding", "multipart/form-data"); + form.attr("enctype", "multipart/form-data"); + form.attr("method", "post"); + form.attr("target", name); + form.attr("action", "{SERVLET_URL}"); + form.bind('submit', startUpload ); + //form.attr("onSubmit", "startUpload()"); + + // reset the form + jQuery("#AjaxFileUpload").each(function(){ + this.reset(); + }); + + upload_index++; +} + +function startUpload(){ + if(!upload_update) + setTimeout("updateUploadStatus()", 500); + + // Init new upload + setTimeout("initUpload()", 500); +} + + +function updateUploadStatus(){ + jQuery.ajax({ + url: "{SERVLET_URL}", + cache: false, + dataType: 'json', + success: function(data){ + // Update + upload_update = true; + if(data == null || data.length == 0){ + upload_update = false; + } + else setTimeout("updateUploadStatus()", 1000); + + // Request upload info + jQuery.each(data, function(index,item){ + // add new list item if needed + if( jQuery("#UploadQueue #"+item.id).size() == 0){ + $("#UploadQueue").append("
  • {PROGHTML}
  • "); + } + // Update data + if(jQuery("#UploadQueue #"+item.id+" .status").size() > 0) + jQuery("#UploadQueue #"+item.id+" .status").html( item.status ); + if(jQuery("#UploadQueue #"+item.id+" .message").size() > 0) + jQuery("#UploadQueue #"+item.id+" .message").html( item.message ); + if(jQuery("#UploadQueue #"+item.id+" .filename").size() > 0) + jQuery("#UploadQueue #"+item.id+" .filename").html( item.filename ); + if(jQuery("#UploadQueue #"+item.id+" .progress").size() > 0) + jQuery("#UploadQueue #"+item.id+" .progress").animate({width: item.percent+"%"}, 'slow'); + + if(jQuery("#UploadQueue #"+item.id+" .total").size() > 0) + jQuery("#UploadQueue #"+item.id+" .total").html( item.total ); + if(jQuery("#UploadQueue #"+item.id+" .uploaded").size() > 0) + jQuery("#UploadQueue #"+item.id+" .uploaded").html( item.uploaded ); + if(jQuery("#UploadQueue #"+item.id+" .speed").size() > 0) + jQuery("#UploadQueue #"+item.id+" .speed").html( item.speed ); + + // remove li when done + if( item.status == "Done" ){ + jQuery("#UploadQueue #"+item.id).delay(5000).fadeOut("slow", function(){ + jQuery(this).remove(); + }); + } + else if( item.status == "Error" ){ + jQuery("#UploadQueue #"+item.id).delay(30000).fadeOut("slow", function(){ + jQuery(this).remove(); + }); + } + }); + }, + error: function(request, textStatus){ + alert(textStatus); + } + }); +} \ No newline at end of file diff --git a/src/zutil/jee/upload/FileUploadListener.java b/src/zutil/jee/upload/FileUploadListener.java new file mode 100644 index 00000000..b4aede85 --- /dev/null +++ b/src/zutil/jee/upload/FileUploadListener.java @@ -0,0 +1,161 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.jee.upload; + +import org.apache.commons.fileupload.ProgressListener; +import zutil.StringUtil; +import zutil.parser.DataNode; +import zutil.parser.DataNode.DataType; + + +/** + * This is a File Upload Listener that is used by Apache + * Commons File Upload to monitor the progress of the + * uploaded file. + */ +public class FileUploadListener implements ProgressListener{ + public static enum Status{ + Initializing, + Uploading, + Processing, + Done, + Error + } + + private String id; + private volatile Status status; + private volatile String filename; + private volatile String message; + private volatile long bytes = 0l; + private volatile long length = 0l; + private volatile int item = 0; + private volatile long time; + + // Speed + private volatile int speed; + private volatile long speedRead; + private volatile long speedTime; + + public FileUploadListener(){ + id = ""+(int)(Math.random()*Integer.MAX_VALUE); + status = Status.Initializing; + filename = ""; + message = ""; + } + + public void update(long pBytesRead, long pContentLength, int pItems) { + if(pContentLength < 0) this.length = pBytesRead; + else this.length = pContentLength; + this.bytes = pBytesRead; + this.item = pItems; + + // Calculate Speed + if(speedTime == 0 || speedTime+1000 < System.currentTimeMillis() || pBytesRead == pContentLength){ + speedTime = System.currentTimeMillis(); + speed = (int)(pBytesRead-speedRead); + speedRead = pBytesRead; + } + //try{Thread.sleep(10);}catch(Exception e){} + + // Set Status + status = Status.Uploading; + time = System.currentTimeMillis(); + } + + protected void setFileName(String filename){ + this.filename = filename; + } + protected void setStatus(Status status){ + this.status = status; + time = System.currentTimeMillis(); + } + protected void setMessage(String msg){ + this.message = msg; + } + + + public String getID(){ + return id; + } + + public String getFilename() { + return filename; + } + + public long getBytesRead() { + return bytes; + } + + public long getContentLength() { + return length; + } + + public long getItem() { + return item; + } + + public Status getStatus(){ + return status; + } + + protected long getTime(){ + return time; + } + + protected String getMessage(){ + return message; + } + + /** + * @return bytes per second + */ + public int getSpeed(){ + return speed; + } + + /** + * Calculate the percent complete + */ + public int getPercentComplete(){ + if(length == 0) + return 0; + return (int)((100 * bytes) / length); + } + + public DataNode getJSON() { + DataNode node = new DataNode( DataType.Map ); + node.set("id", id); + + node.set("status", status.toString()); + node.set("message", message.replaceAll("\"", "\\\"") ); + node.set("filename", filename); + node.set("percent", getPercentComplete()); + + node.set("uploaded", StringUtil.formatByteSizeToString(bytes)); + node.set("total", StringUtil.formatByteSizeToString(length)); + node.set("speed", StringUtil.formatByteSizeToString(speed)+"/s"); + return node; + } +} diff --git a/src/zutil/log/CompactLogFormatter.java b/src/zutil/log/CompactLogFormatter.java new file mode 100755 index 00000000..c72751cc --- /dev/null +++ b/src/zutil/log/CompactLogFormatter.java @@ -0,0 +1,170 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log; + +import zutil.StringUtil; +import zutil.io.StringOutputStream; + +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.logging.Formatter; +import java.util.logging.LogRecord; +import java.util.regex.Pattern; + +public class CompactLogFormatter extends Formatter{ + /** The split pattern where the **/ + private static final Pattern splitter = Pattern.compile("\n"); + /** the stream should print time stamp **/ + private boolean timeStamp = true; + /** The time stamp style **/ + private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + /** If displaying class names are enabled **/ + private boolean className = true; + /** If displaying method names are enabled **/ + private boolean methodName = false; + /** Specifies the max length of the longest class name **/ + private int max_class_name = 0; + /** Cache for the class padding **/ + private static HashMap padd_cache = new HashMap(); + /** Date temp file **/ + private Date date = new Date(); + + + @Override + public String format(LogRecord record) { + StringBuilder prefix = new StringBuilder(); + + if( timeStamp ){ + date.setTime( record.getMillis() ); + prefix.append(dateFormatter.format(date)); + prefix.append(' '); + } + + switch( record.getLevel().intValue() ){ + case /* SEVERE */ 1000: prefix.append("[SEVERE] "); break; + case /* WARNING */ 900 : prefix.append("[WARNING]"); break; + case /* INFO */ 800 : prefix.append("[INFO] "); break; + case /* CONFIG */ 700 : prefix.append("[CONFIG] "); break; + case /* FINE */ 500 : prefix.append("[FINE] "); break; + case /* FINER */ 400 : prefix.append("[FINER] "); break; + case /* FINEST */ 300 : prefix.append("[FINEST] "); break; + } + prefix.append(' '); + + if( className ){ + prefix.append(paddClassName(record.getSourceClassName())); + } + if(methodName){ + prefix.append(record.getSourceMethodName()); + } + prefix.append(": "); + + StringBuilder ret = new StringBuilder(); + if( record.getMessage() != null ){ + String[] array = splitter.split( record.getMessage() ); + for( int i=0; i 0 ) + ret.append( prefix ); + ret.append( array[i] ); + } + ret.append( '\n' ); + } + + if( record.getThrown() != null ){ + StringOutputStream out = new StringOutputStream(); + record.getThrown().printStackTrace(new PrintStream(out)); + String[] array = splitter.split( out.toString() ); + for( int i=0; i 0 ) + ret.append( prefix ); + ret.append( array[i] ); + } + ret.append( '\n' ); + } + return ret.toString(); + } + + /** + * If the formatter should add a time stamp in front of the log message + * + * @param enable set to True to activate time stamp + */ + public void enableTimeStamp(boolean enable){ + timeStamp = enable; + } + + /** + * The DateFormat to print in the time stamp + * + * @param ts is the String to send to SimpleDateFormat + */ + public void setTimeStamp(String ts){ + dateFormatter = new SimpleDateFormat(ts); + } + + /** + * If the formatter should add the class/source name in front of the log message + * + * @param enable set to True to activate class/source name + */ + public void enableClassName(boolean enable){ + className = enable; + } + + /** + * If the formatter should add the class/source name in front of the log message + * + * @param enable set to True to activate class/source name + */ + public void enableMethodName(boolean enable){ + methodName = enable; + } + + /** + * @return the Class name + */ + private String paddClassName(String source){ + String cStr = padd_cache.get(source); + if(cStr == null || cStr.length() != max_class_name) { + cStr = source.substring(source.lastIndexOf('.') + 1); // Remove packages + if(cStr.lastIndexOf('$') >= 0) // extract subclass name + cStr = cStr.substring(cStr.lastIndexOf('$')+1); + + if (cStr.length() > max_class_name) + max_class_name = cStr.length(); + + cStr += StringUtil.getSpaces(max_class_name - cStr.length()); + padd_cache.put(source, cStr); + } + return cStr; + } + +} diff --git a/src/zutil/log/InputStreamLogger.java b/src/zutil/log/InputStreamLogger.java new file mode 100755 index 00000000..9628a6cd --- /dev/null +++ b/src/zutil/log/InputStreamLogger.java @@ -0,0 +1,96 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log; + +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class will log all data that passes through a InputStream. + * The logging is done with Javas standard Logger with Level.FINEST. + * + * Created by Ziver on 2015-10-15. + */ +public class InputStreamLogger extends InputStream implements StreamLogger.LogCallback { + private static final Logger logger = LogUtil.getLogger(); + + private InputStream in; + private StreamLogger log; + + public InputStreamLogger(InputStream in){ + this(null, in); + } + public InputStreamLogger(String prefix, InputStream in){ + this.in = in; + this.log = new StreamLogger(prefix, this); + } + + + public boolean isLoggable(){ + return logger.isLoggable(Level.FINEST); + } + public void log(String msg){ + logger.finest(msg); + } + + //************** PROXY METHODS ****************** + public int read() throws IOException{ + int n = in.read(); + log.log(n); + return n; + } + public int read(byte b[]) throws IOException { + int n = in.read(b); + log.log(b, 0, n); + return n; + } + public int read(byte b[], int off, int len) throws IOException { + int n = in.read(b, off, len); + log.log(b, off, n); + return n; + } + public long skip(long n) throws IOException { + return in.skip(n); + } + public int available() throws IOException { + return in.available(); + } + public void close() throws IOException { + in.close(); + log.flushLog(); + } + public void mark(int readlimit) { + in.mark(readlimit); + } + public void reset() throws IOException { + in.reset(); + log.clearLog(); + } + public boolean markSupported() { + return in.markSupported(); + } +} diff --git a/src/zutil/log/LogUtil.java b/src/zutil/log/LogUtil.java new file mode 100755 index 00000000..9c083b49 --- /dev/null +++ b/src/zutil/log/LogUtil.java @@ -0,0 +1,140 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log; + +import zutil.io.file.FileUtil; + +import java.io.FileInputStream; +import java.util.logging.*; + +/** + * Utility functions for the standard Java Logger + * + * @author Ziver + */ +public class LogUtil { + private static final Logger logger = Logger.getLogger( LogUtil.class.getName() ); + + + private LogUtil(){} + + /** + * @return a new Logger for the calling class + */ + public static Logger getLogger(){ + return Logger.getLogger(getCallingClass()); + } + + /** + * @return the parent class other than Logger in the stack + */ + public static String getCallingClass(){ + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + for(int i=1; i c, Level level){ + setLevel(c.getName(), level); + } + + /** + * Sets the log level for a specified logger + */ + public static void setLevel(String name, Level level){ + logger.fine("Changing log level of \""+name+"\" to \""+level.getLocalizedName()+"\""); + Logger newLogger = Logger.getLogger(name); + newLogger.setLevel(level); + // Check if the logger has a handler + if( newLogger.getHandlers().length > 0 ){ + // Set the level on the handlers if its level is higher + for (Handler handler : newLogger.getHandlers()) { + if(handler.getLevel().intValue() < level.intValue()) + handler.setLevel(level); + } + } + } + + public static boolean isLoggable(Class clazz, Level level){ + return Logger.getLogger(clazz.getName()).isLoggable(level); + } + + public static void readConfiguration(String file){ + try{ + FileInputStream in = new FileInputStream(FileUtil.find(file)); + LogManager.getLogManager().readConfiguration(in); + in.close(); + } catch (Exception e){ + logger.log(Level.SEVERE, null, e); + } + } +} diff --git a/src/zutil/log/OutputStreamLogger.java b/src/zutil/log/OutputStreamLogger.java new file mode 100755 index 00000000..6eb77566 --- /dev/null +++ b/src/zutil/log/OutputStreamLogger.java @@ -0,0 +1,82 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class will log all data that passes through a InputStream. + * The logging is done with Javas standard Logger with Level.FINEST. + * + * Created by Ziver on 2015-10-15. + */ +public class OutputStreamLogger extends OutputStream implements StreamLogger.LogCallback { + private static final Logger logger = LogUtil.getLogger(); + + private OutputStream out; + private StreamLogger log; + + + public OutputStreamLogger(OutputStream out){ + this(null, out); + } + public OutputStreamLogger(String prefix, OutputStream out){ + this.out = out; + this.log = new StreamLogger(prefix, this); + } + + + public boolean isLoggable(){ + return logger.isLoggable(Level.FINEST); + } + public void log(String msg){ + logger.finest(msg); + } + + //************** PROXY METHODS ****************** + public void write(int b) throws IOException{ + out.write(b); + log.log(b); + } + public void write(byte b[]) throws IOException { + out.write(b, 0, b.length); + log.log(b, 0, b.length); + } + public void write(byte b[], int off, int len) throws IOException { + out.write(b, off, len); + log.log(b, off, len); + } + public void flush() throws IOException { + out.flush(); + log.flushLog(); + } + public void close() throws IOException { + out.close(); + log.flushLog(); + } +} diff --git a/src/zutil/log/StreamLogger.java b/src/zutil/log/StreamLogger.java new file mode 100755 index 00000000..e9e6731c --- /dev/null +++ b/src/zutil/log/StreamLogger.java @@ -0,0 +1,88 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log; + +/** + * Created by Ziver on 2015-10-15. + */ +public class StreamLogger { + private static final byte DELIMETER = '\n'; + private static final int MAX_BUFFER_SIZE = 1024; + + + private LogCallback logger; + private String prefix; + private StringBuilder buffer; + + + protected StreamLogger(String prefix, LogCallback logger){ + if(logger == null) + throw new NullPointerException("LogCallback can not be NULL"); + this.prefix = prefix; + this.logger = logger; + this.buffer = new StringBuilder(); + } + + + protected void log(int n){ + if(n < 0 || n == DELIMETER) + flushLog(); + else + buffer.append((char)n); + if(buffer.length() > MAX_BUFFER_SIZE) + flushLog(); + } + protected void log(byte[] b, int off, int len){ + if (logger.isLoggable()) { + for(int i=0; i MAX_BUFFER_SIZE) + flushLog(); + } + } + + protected void flushLog(){ + if(buffer.length() > 0) { + if (prefix != null) + logger.log(prefix + ": " + buffer.toString()); + else + logger.log(buffer.toString()); + clearLog(); + } + } + protected void clearLog(){ + buffer.delete(0, buffer.length()); + } + + + public interface LogCallback{ + public boolean isLoggable(); + public void log(String msg); + } +} diff --git a/src/zutil/log/logging.properties.example b/src/zutil/log/logging.properties.example new file mode 100755 index 00000000..b58bb710 --- /dev/null +++ b/src/zutil/log/logging.properties.example @@ -0,0 +1,10 @@ +# logging.properties +# LogUtil.readConfiguration("logging.properties"); + +handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler +java.util.logging.ConsoleHandler.level = ALL +java.util.logging.ConsoleHandler.formatter = zutil.log.CompactLogFormatter +java.util.logging.FileHandler.level = ALL +java.util.logging.FileHandler.formatter = zutil.log.CompactLogFormatter + +zutil.level = ALL \ No newline at end of file diff --git a/src/zutil/log/net/NetLogClient.fxml b/src/zutil/log/net/NetLogClient.fxml new file mode 100644 index 00000000..96574441 --- /dev/null +++ b/src/zutil/log/net/NetLogClient.fxml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/zutil/log/net/NetLogClient.java b/src/zutil/log/net/NetLogClient.java new file mode 100644 index 00000000..f0912266 --- /dev/null +++ b/src/zutil/log/net/NetLogClient.java @@ -0,0 +1,91 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + +import zutil.log.LogUtil; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.logging.Level; +import java.util.logging.Logger; + + +public class NetLogClient extends Thread{ + private static final Logger logger = LogUtil.getLogger(); + + private ConcurrentLinkedQueue listeners; + private Socket s; + private ObjectOutputStream out; + + public NetLogClient(String host, int port) throws UnknownHostException, IOException{ + s = new Socket(host, port); + out = new ObjectOutputStream(s.getOutputStream()); + listeners = new ConcurrentLinkedQueue(); + this.start(); + } + + public void addListener(NetLogListener listener){ + logger.info("Registring new NetLogListener: "+listener.getClass().getName()); + listeners.add( listener ); + } + + public void run(){ + try{ + ObjectInputStream in = new ObjectInputStream(s.getInputStream()); + while( true ){ + Object o = in.readObject(); + + for( NetLogListener listener : listeners ){ + if( o instanceof NetLogMessage ) + listener.handleLogMessage((NetLogMessage)o); + else if( o instanceof NetLogExceptionMessage ) + listener.handleExceptionMessage((NetLogExceptionMessage)o); + else if( o instanceof NetLogStatusMessage ) + listener.handleStatusMessage((NetLogStatusMessage)o); + else + logger.warning("Received unknown message: "+o.getClass().getName()); + } + } + } catch( Exception e ){ + logger.log(Level.SEVERE, null, e); + close(); + } + } + + + + public void close(){ + try{ + this.interrupt(); + s.close(); + } catch (Exception e){ + logger.log(Level.SEVERE, "Unable to close Client Socket.", e); + } + } +} diff --git a/src/zutil/log/net/NetLogClientInstance.css b/src/zutil/log/net/NetLogClientInstance.css new file mode 100644 index 00000000..69bf6e9d --- /dev/null +++ b/src/zutil/log/net/NetLogClientInstance.css @@ -0,0 +1,35 @@ +/* LOG LEVELS */ +.SEVERE { + -fx-control-inner-background: palevioletred; + -fx-accent: derive(-fx-control-inner-background, -40%); + -fx-cell-hover-color: derive(-fx-control-inner-background, -20%); +} +.WARNING { + -fx-control-inner-background: yellow; + -fx-accent: derive(-fx-control-inner-background, -40%); + -fx-cell-hover-color: derive(-fx-control-inner-background, -20%); +} +.INFO { } +.FINE { + -fx-control-inner-background: lavender; + -fx-accent: derive(-fx-control-inner-background, -40%); + -fx-cell-hover-color: derive(-fx-control-inner-background, -20%); +} +.FINER { + -fx-control-inner-background: lightblue ; + -fx-accent: derive(-fx-control-inner-background, -40%); + -fx-cell-hover-color: derive(-fx-control-inner-background, -20%); +} +.FINEST { + -fx-control-inner-background: skyblue; + -fx-accent: derive(-fx-control-inner-background, -40%); + -fx-cell-hover-color: derive(-fx-control-inner-background, -20%); +} + +/* Clear empty rows */ +.table-row-cell:empty { + -fx-background-color: null; +} +.table-row-cell:empty .table-cell { + -fx-border-width: 0px; +} \ No newline at end of file diff --git a/src/zutil/log/net/NetLogClientInstance.fxml b/src/zutil/log/net/NetLogClientInstance.fxml new file mode 100644 index 00000000..02054112 --- /dev/null +++ b/src/zutil/log/net/NetLogClientInstance.fxml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    diff --git a/src/zutil/log/net/NetLogExceptionMessage.java b/src/zutil/log/net/NetLogExceptionMessage.java new file mode 100644 index 00000000..71f84023 --- /dev/null +++ b/src/zutil/log/net/NetLogExceptionMessage.java @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + +import zutil.net.nio.message.Message; + +import java.util.logging.LogRecord; + +public class NetLogExceptionMessage extends Message { + private static final long serialVersionUID = 1L; + + private int count; + private String name; + private String message; + private String stackTrace; + + NetLogExceptionMessage(String name, String message, String stackTrace){ + this.count = 1; + this.name = name; + this.message = message; + this.stackTrace = stackTrace; + } + + public NetLogExceptionMessage(LogRecord record) { + Throwable exception = record.getThrown(); + + this.count = 1; + this.name = exception.getClass().getName(); + this.message = exception.getMessage(); + this.stackTrace = ""; + for(int i=0; i() { + // public void handle(Event e) { + // handleDisconnectAction(e); + // } + //}); + } + } +} \ No newline at end of file diff --git a/src/zutil/log/net/NetLogGuiClientInstance.java b/src/zutil/log/net/NetLogGuiClientInstance.java new file mode 100644 index 00000000..81aec96f --- /dev/null +++ b/src/zutil/log/net/NetLogGuiClientInstance.java @@ -0,0 +1,222 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.event.Event; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.*; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.util.Callback; +import zutil.log.LogUtil; + +import java.net.URL; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class NetLogGuiClientInstance implements Initializable, NetLogListener { + private static final Logger logger = LogUtil.getLogger(); + private static enum Status{RUNNING, PAUSED, DISCONNECTED} + + // Logic variables + private NetLogClient net; + private Status status; + + // UI elements + @FXML private ToggleButton pauseButton; + @FXML private Label levelLabel; + @FXML private ComboBox levelComboBox; + @FXML private Label intervalLabel; + @FXML private ComboBox intervalComboBox; + @FXML private ProgressBar progressBar; + @FXML private Label errorLabel; + @FXML private Label logCountLabel; + + @FXML private TableView logTable; + @FXML private TableColumn logTimestampColumn; + @FXML private TableColumn logLevelColumn; + @FXML private TableColumn logColumn; + + @FXML private TableView exceptionTable; + @FXML private TableColumn exCountColumn; + @FXML private TableColumn exNameColumn; + @FXML private TableColumn exMessageColumn; + @FXML private TableColumn exStackTraceColumn; + + + public void initialize(URL arg0, ResourceBundle arg1) { + // Connect to Server + try{ + net = new NetLogClient("127.0.0.1", 5050); + net.addListener( this ); + status = Status.RUNNING; + }catch(Exception e){ + logger.log(Level.SEVERE, null, e); + status = Status.DISCONNECTED; + errorLabel.setText(e.getMessage()); + } + updateStatus(); + + // Setup Gui + logTimestampColumn.setCellValueFactory(new PropertyValueFactory("timestamp")); + logLevelColumn.setCellValueFactory(new PropertyValueFactory("level")); + logLevelColumn.setCellFactory(new RowCssCellFactory(){ + public String getStyleName(String item){ + return item; + } + }); + logColumn.setCellValueFactory(new PropertyValueFactory("log")); + + exCountColumn.setCellValueFactory(new PropertyValueFactory("count")); + exNameColumn.setCellValueFactory(new PropertyValueFactory("name")); + exMessageColumn.setCellValueFactory(new PropertyValueFactory("message")); + exStackTraceColumn.setCellValueFactory(new PropertyValueFactory("stackTrace")); + } + + /************* NETWORK *****************/ + public void handleLogMessage(NetLogMessage msg) { + if(status == Status.RUNNING){ + logTable.getItems().add(msg); + + Platform.runLater(new Runnable() { + public void run() { + logCountLabel.setText("" + (Long.parseLong(logCountLabel.getText()) + 1)); + } + }); + } + } + + public void handleExceptionMessage(NetLogExceptionMessage msg) { + if(status == Status.RUNNING){ + exceptionTable.getItems().remove(msg); + exceptionTable.getItems().add(msg); + } + } + + public void handleStatusMessage(NetLogStatusMessage msg) { + if(status == Status.RUNNING){ + + } + } + + /*************** GUI *******************/ + @FXML + protected void handlePauseAction(ActionEvent event) { + if(status == Status.RUNNING){ + status = Status.PAUSED; + logger.info("Logging paused"); + } + else if(status == Status.PAUSED){ + status = Status.RUNNING; + logger.info("Logging Unpaused"); + } + updateStatus(); + } + + @FXML + protected void handleDisconnectAction(Event event) { + logger.info("Disconnecting from Log Server"); + net.close(); + status = Status.DISCONNECTED; + updateStatus(); + } + + @FXML + protected void handleLevelChanged(ActionEvent event) { + logger.info("Updating Log Level"); + } + + @FXML + protected void handleIntervalChanged(ActionEvent event) { + logger.info("Updating Log Interval"); + } + + private void updateStatus(){ + if(progressBar == null || pauseButton == null){ + return; + } + + if(status == Status.RUNNING){ + progressBar.setProgress(-1.0); + pauseButton.setText("Pause"); + } + else if(status == Status.PAUSED){ + progressBar.setProgress(1.0); + pauseButton.setText("Unpause"); + } + else if(status == Status.DISCONNECTED){ + pauseButton.setDisable(true); + levelLabel.setDisable(true); + levelComboBox.setDisable(true); + intervalLabel.setDisable(true); + intervalComboBox.setDisable(true); + + logTable.setDisable(true); + exceptionTable.setDisable(true); + + progressBar.setProgress(0); + logCountLabel.setDisable(true); + } + } + + /** + * http://stackoverflow.com/questions/13697115/javafx-tableview-colors + */ + public abstract class RowCssCellFactory implements Callback, TableCell> { + + public TableCell call(TableColumn p) { + TableCell cell = new TableCell() { + @Override + public void updateItem(T item, boolean empty) { + super.updateItem(item, empty); + setText(empty ? null : getString()); + setGraphic(null); + + String style = getStyleName(item); + if(style != null){ + TableRow row = getTableRow(); + row.getStyleClass().add(style); + } + } + + @Override + public void updateSelected(boolean upd){ + super.updateSelected(upd); + } + + + private String getString() { + return getItem() == null ? "NULL" : getItem().toString(); + } + }; + return cell; + } + + public abstract String getStyleName(T item); + } +} \ No newline at end of file diff --git a/src/zutil/log/net/NetLogListener.java b/src/zutil/log/net/NetLogListener.java new file mode 100644 index 00000000..f9095e98 --- /dev/null +++ b/src/zutil/log/net/NetLogListener.java @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + + +public interface NetLogListener { + /** + * Handle incoming log messages + */ + public void handleLogMessage( NetLogMessage log ); + + /** + * Handle incoming exception messages + */ + public void handleExceptionMessage( NetLogExceptionMessage exception ); + + /** + * Handle incoming status messages + */ + public void handleStatusMessage( NetLogStatusMessage status ); +} diff --git a/src/zutil/log/net/NetLogMessage.java b/src/zutil/log/net/NetLogMessage.java new file mode 100644 index 00000000..44c673a0 --- /dev/null +++ b/src/zutil/log/net/NetLogMessage.java @@ -0,0 +1,111 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + +import zutil.net.nio.message.Message; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.logging.LogRecord; + +public class NetLogMessage extends Message { + private static final long serialVersionUID = 1L; + private static final SimpleDateFormat dataFormat = + new SimpleDateFormat("yyyy--MM-dd HH:mm:ss"); + + private long timestamp; + private String level; + private int threadID; + private String className; + private String methodName; + private String log; + + public NetLogMessage(String level, long timestamp, String log){ + this.level = level; + this.timestamp = timestamp; + this.log = log; + } + + public NetLogMessage( LogRecord record ){ + timestamp = record.getMillis(); + level = record.getLevel().getName(); + threadID = record.getThreadID(); + className = record.getSourceClassName(); + methodName = record.getSourceMethodName(); + log = record.getMessage(); + } + + + + public String getTimestamp() { + return dataFormat.format(new Date(timestamp)); + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + + public int getThreadID() { + return threadID; + } + + public void setThreadID(int threadID) { + this.threadID = threadID; + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public String getLog() { + return log; + } + + public void setLog(String log) { + this.log = log; + } + + +} diff --git a/src/zutil/log/net/NetLogServer.java b/src/zutil/log/net/NetLogServer.java new file mode 100644 index 00000000..69c9c875 --- /dev/null +++ b/src/zutil/log/net/NetLogServer.java @@ -0,0 +1,176 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + +import zutil.log.LogUtil; +import zutil.net.nio.message.Message; +import zutil.net.threaded.ThreadedTCPNetworkServer; +import zutil.net.threaded.ThreadedTCPNetworkServerThread; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + + +public class NetLogServer extends Handler { + private static final Logger logger = LogUtil.getLogger(); + + private NetLogNetwork net; + private ConcurrentHashMap exceptions; + + /** + * @param port the port the server will listen on + */ + public NetLogServer(int port) { + super(); + exceptions = new ConcurrentHashMap(); + net = new NetLogNetwork(port); + net.start(); + } + + + public void publish(LogRecord record) { + // ensure that this log record should be logged by this Handler + if (!isLoggable(record)) + return; + + // Output the formatted data to the file + if(record.getThrown() != null){ + NetLogExceptionMessage exception = new NetLogExceptionMessage(record); + if(!exceptions.containsKey(exception)){ + logger.finest("Received new exception: "+exception); + exceptions.put(exception, exception); + net.sendMessage( exception ); + } + else{ + exception = exceptions.get(exception); + exception.addCount(1); + logger.finest("Received known exception(Count: "+exception.getCount()+"): "+exception); + net.sendMessage( exception ); + } + } + else{ + NetLogMessage log = new NetLogMessage(record); + net.sendMessage( log ); + } + } + + public void flush() {} + + public void close() { + net.close(); + } + + + class NetLogNetwork extends ThreadedTCPNetworkServer{ + private ConcurrentLinkedQueue threads; + + public NetLogNetwork(int port) { + super(port); + threads = new ConcurrentLinkedQueue(); + } + + public void sendMessage(Message log){ + for( NetLogServerThread thread : threads ){ + thread.sendMessage( log ); + } + } + + @Override + protected ThreadedTCPNetworkServerThread getThreadInstance(Socket s) { + try { + NetLogServerThread thread = new NetLogServerThread(s); + return thread; + } catch (IOException e) { + logger.log(Level.SEVERE, "Unable to start Client thread", e); + } + return null; + } + + + class NetLogServerThread implements ThreadedTCPNetworkServerThread{ + private ObjectOutputStream out; + private ObjectInputStream in; + private Socket s; + + public NetLogServerThread(Socket s) throws IOException{ + this.s = s; + logger.info("Client connected: "+s.getInetAddress()); + out = new ObjectOutputStream( s.getOutputStream() ); + in = new ObjectInputStream( s.getInputStream() ); + + sendAllExceptions(); + threads.add( this ); + } + + public void sendMessage(Message msg){ + try { + out.writeObject( msg ); + out.reset(); + } catch (Exception e) { + this.close(); + logger.log(Level.SEVERE, "Unable to send message to client: "+s.getInetAddress(), e); + } + } + + public void sendAllExceptions(){ + logger.fine("Sending all exceptions to client: "+s.getInetAddress()); + for(NetLogExceptionMessage e : exceptions.values()) + sendMessage(e); + } + + public void run() { + try { + while( true ){ + in.readObject(); + } + } catch (Exception e) { + logger.log(Level.SEVERE, null, e); + } finally { + this.close(); + } + } + + + public void close(){ + try { + threads.remove(this); + logger.info("Client disconnected: "+s.getInetAddress()); + out.close(); + s.close(); + } catch (IOException e) { + logger.log(Level.SEVERE, "Unable to close Client Socket", e); + } + } + } + } +} diff --git a/src/zutil/log/net/NetLogStatusMessage.java b/src/zutil/log/net/NetLogStatusMessage.java new file mode 100644 index 00000000..2195871b --- /dev/null +++ b/src/zutil/log/net/NetLogStatusMessage.java @@ -0,0 +1,34 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + +import zutil.net.nio.message.Message; + +public class NetLogStatusMessage extends Message{ + private static final long serialVersionUID = 1L; + + public long totalMemory; + public long freememory; +} diff --git a/src/zutil/math/Tick.java b/src/zutil/math/Tick.java new file mode 100644 index 00000000..c406760c --- /dev/null +++ b/src/zutil/math/Tick.java @@ -0,0 +1,125 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.math; + +public class Tick { + + /** + * Ticks a given string(increments the string with one) + * + * @param ts is the string to tick + * @param maxChar is the maximum number of characters in the string + * @return the ticked string + */ + public static String tick(String ts, int maxChar){ + StringBuffer ret = new StringBuffer(ts.trim()); + int index = ret.length()-1; + + if(ret.length() < maxChar){ + ret.append('a'); + } + else{ + while(index >= 0){ + char c = increment(ret.charAt(index)); + if(c != 0){ + if(index == 0 && ret.length() < maxChar) ret.append('a'); + if(index == 0) ret = new StringBuffer(""+c); + else ret.setCharAt(index,c); + break; + } + else{ + //ret.setCharAt(index,'a'); + ret.deleteCharAt(index); + index--; + } + } + } + + return ret.toString(); + } + + /** + * Increments the char with one after the swedish alfabet + * + * @param c is the char to increment + * @return the incremented char in lowercase 0 if it reached the end + */ + public static char increment(char c){ + switch(Character.toLowerCase(c)){ + case 'z': return (char)134; + case (char)134: return (char)132; + case (char)132: return (char)148; + } + c = (char)(Character.toLowerCase(c) + 1); + if(isAlphabetic(c)){ + return c; + } + return 0; + } + + /** + * Checks if the char is a valid character in + * the Swedish alphabet + * + * @param c is the char to check + * @return true if the char is a valid letter + */ + public static boolean isAlphabetic(char c){ + switch(Character.toLowerCase(c)){ + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case (char)134: + case (char)132: + case (char)148: + return true; + default: + return false; + } + } +} diff --git a/src/zutil/math/ZMath.java b/src/zutil/math/ZMath.java new file mode 100644 index 00000000..eb712940 --- /dev/null +++ b/src/zutil/math/ZMath.java @@ -0,0 +1,101 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.math; + +import java.math.BigInteger; + +/** + * Very Simple math functions + * + * @author Ziver + */ +public class ZMath { + + /** + * Calculates the percentage of the values + */ + public static double percent(int min, int max, int value){ + return ((double)(value-min)/(max-min))*100; + } + + /** + * Solves the equation: x^2 + px + q = 0 + * + * @return the two values of x as an array + */ + public static double[] pqFormula(double p, double q){ + double[] ret = new double[2]; + double t = (p/2); + ret[0] = Math.sqrt( t*t - q ); + ret[1] = -ret[0]; + t *= -1; + ret[0] += t; + ret[1] += t; + return ret; + } + + /** + * Solves the equation: x^2 + px + q = 0. + * WARNING: This uses only BigInteger, thereby removing the decimals in the calculation + * + * @return the two values of x as an array + */ + public static BigInteger[] pqFormula(BigInteger p, BigInteger q){ + BigInteger[] ret = new BigInteger[2]; + BigInteger t = p.divide( BigInteger.valueOf(2) ); + ret[0] = ZMath.sqrt( t.multiply( t ).subtract( q ) ); + ret[1] = ret[0].negate(); + t = t.negate(); + ret[0] = ret[0].add( t ); + ret[1] = ret[1].add( t ); + return ret; + } + + /** + * Calculates the square root of a big number + * + */ + public static BigInteger sqrt(BigInteger value){ + BigInteger op = value; + BigInteger res = BigInteger.ZERO; + BigInteger one = BigInteger.ONE; + + while( one.compareTo( op ) < 0 ){ + one = one.shiftLeft( 2 ); + } + one = one.shiftRight(2); + + while( !one.equals( BigInteger.ZERO ) ){ + if( op.compareTo( res.add( one ) ) >= 0 ){ + op = op.subtract( res.add( one ) ); + res = res.add( one.shiftLeft( 1 ) ); + } + res = res.shiftRight( 1 ); + one = one.shiftRight( 2 ); + } + + return res; + } +} diff --git a/src/zutil/net/FTPClient.java b/src/zutil/net/FTPClient.java new file mode 100644 index 00000000..c7e330a7 --- /dev/null +++ b/src/zutil/net/FTPClient.java @@ -0,0 +1,365 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +import zutil.io.IOUtil; + +import javax.security.auth.login.AccountException; +import java.io.*; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.regex.Pattern; + +/** + * A simple FTP client class + * + * @author Ziver + * + * http://en.wikipedia.org/wiki/List_of_FTP_commands + * http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes + * http://www.ietf.org/rfc/rfc959.txt + * + * TODO: file info, rename, Active mode + */ +public class FTPClient extends Thread{ + public static final int FTP_PORT = 21; + public static final int FTP_DATA_PORT = 20; + public static final int FTP_NOOP_INT = 120; + + public static enum FTPConnectionType{ + ACTIVE, + PASSIVE + } + + public static enum FTPReturnCode{ + UNKNOWN ( -1 ), + + USER_OK ( 331 ), + NEED_PASS ( 331 ), + LOGIN_NO ( 530 ), + LOGIN_OK ( 230 ), + + ENTERING_PASSIVE ( 227 ), + FILE_ACTION_OK ( 250 ), + PATH_CREATED ( 257 ); + + private int code; + private FTPReturnCode(int code){ + this.code = code; + } + + public boolean isError(){ + return code >= 400; + } + + public static FTPReturnCode fromCode(int code){ + for(FTPReturnCode type : FTPReturnCode.values()){ + if(code == type.code) return type; + } + return UNKNOWN; + } + } + //*************************************************** + + private FTPConnectionType connectionType; + private BufferedReader in; + private Writer out; + private Socket socket; + private long last_sent; + + /** + * Creates a FTP connection and logs in + * + * @param url the address to server + * @param port port number + * @param user login username + * @param pass password + * @param conn_type connection type + */ + public FTPClient(String url, int port, String user, String pass, FTPConnectionType conn_type) throws UnknownHostException, IOException, AccountException{ + socket = new Socket(url, port); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new OutputStreamWriter(socket.getOutputStream()); + connectionType = conn_type; + + readCommand(); + sendCommand("USER "+user); + sendNoReplyCommand("PASS "+pass); + String tmp = readCommand(); + if(parseReturnCode(tmp) == FTPReturnCode.LOGIN_NO){ + close(); + throw new AccountException(tmp); + } + + start(); + } + +//************************************************************************************** +//********************************* Command channel ************************************ + + /** + * Sends the given command to the server and returns a status integer + * + * @return last line received from the server + */ + private FTPReturnCode sendCommand(String cmd) throws IOException{ + sendNoReplyCommand(cmd); + return parseReturnCode( readCommand( ) ); + } + + /** + * Sends a command and don't cares about the reply + */ + private void sendNoReplyCommand(String cmd) throws IOException{ + last_sent = System.currentTimeMillis(); + out.append(cmd).append('\n'); + } + + /** + * Reads from the command channel until there are nothing + * left to read and returns the last line + * + * @return last line received by the server + */ + private String readCommand() throws IOException{ + String tmp = in.readLine(); + while(!Character.isWhitespace(tmp.charAt(3))){ + tmp = in.readLine(); + if(parseReturnCode(tmp).isError()) throw new IOException(tmp); + } + return tmp; + } + + /** + * Parses the return line from the server and returns the status code + * + * @param msg message String from the server + * @return a status code response + */ + private FTPReturnCode parseReturnCode(String msg){ + return FTPReturnCode.fromCode(Integer.parseInt(msg.substring(0, 3))); + } + +//************************************************************************************** +//****************************** File system actions ************************************ + + /** + * Returns a LinkedList with names of all the files in the directory + * + * @deprecated + * @return List with filenames + */ + public String[] getFileList(String path) throws IOException{ + BufferedInputStream data_in = getDataInputStream(); + sendCommand("NLST "+path); + + String data = new String(IOUtil.getContent(data_in)); + + data_in.close(); + readCommand(); + return data.split("[\n\r]"); + } + + /** + * Returns information about a file or directory + * + * @deprecated + * @return a List of Strings with information + */ + public String getFileInfo(String path) throws IOException{ + Pattern regex = Pattern.compile("\\s{1,}"); + + BufferedInputStream data_in = getDataInputStream(); + sendCommand("LIST "+path); + + String data = new String(IOUtil.getContent(data_in)); + + data_in.close(); + readCommand(); + return data; + } + + /** + * Creates a file in the server with the given data + * + * @param path filepath + * @param data data to put in the file + */ + public void sendFile(String path, String data) throws IOException{ + BufferedOutputStream data_out = getDataOutputStream(); + sendCommand("STOR "+path); + + byte[] byte_data = data.getBytes(); + data_out.write(byte_data, 0, byte_data.length); + data_out.close(); + + readCommand(); + } + + /** + * Creates a directory in the server + * + * @param path The path to the directory + */ + public boolean createDir(String path) throws IOException{ + if(sendCommand("MKD "+path) == FTPReturnCode.PATH_CREATED) + return true; + return false; + } + + /** + * Returns a InputStream for a file on the server + * WARNING: you must run readCommand(); after you close the stream + * + * @return a stream with file data + */ + private BufferedInputStream getFileInputStream(String path) throws IOException{ + BufferedInputStream input = getDataInputStream(); + sendCommand("RETR "+path); + return input; + } + + /** + * Download a file from the server to a local file + * + * @param source source file on the server + * @param destination local destination file + */ + public void getFile(String source, String destination) throws IOException{ + BufferedInputStream ext_file_in = getFileInputStream(source); + BufferedOutputStream local_file_out = new BufferedOutputStream(new FileOutputStream(new File(destination))); + + IOUtil.copyStream(ext_file_in, local_file_out); + readCommand(); + } + + /** + * Remove a file from the FTP server + * + * @return true if the command was successful, false otherwise + */ + public boolean removeFile(String path) throws IOException{ + if(sendCommand("DELE "+path) == FTPReturnCode.FILE_ACTION_OK) + return true; + return false; + } + + /** + * Removes a directory from the FTP server + * + * @return True if the command was successful or false otherwise + */ + public boolean removeDir(String path) throws IOException{ + if(sendCommand("RMD "+path) == FTPReturnCode.FILE_ACTION_OK) + return true; + return false; + } + +//************************************************************************************** +//******************************** Data Connection ************************************* + + /** + * Start a data connection to the server. + * + * @return a PrintStream for the channel + */ + public BufferedOutputStream getDataOutputStream() throws IOException{ + if(connectionType == FTPConnectionType.PASSIVE){ // Passive Mode + int port = setPassiveMode(); + Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port); + return new BufferedOutputStream(data_socket.getOutputStream()); + } + else{ // Active Mode + return null; + } + } + + /** + * Start a data connection to the server. + * + * @return a BufferedReader for the data channel + */ + public BufferedInputStream getDataInputStream() throws IOException{ + if(connectionType == FTPConnectionType.PASSIVE){ // Passive Mode + int port = setPassiveMode(); + Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port); + return new BufferedInputStream(data_socket.getInputStream()); + } + else{ // Active Mode + return null; + } + } + + + /** + * Sets Passive mode to the server + * + * @return a port number for data channel + */ + private int setPassiveMode() throws IOException{ + sendNoReplyCommand("PASV"); + String ret_msg = readCommand(); + if(parseReturnCode(ret_msg) != FTPReturnCode.ENTERING_PASSIVE){ + throw new IOException("Passive mode rejected by server: "+ret_msg); + } + ret_msg = ret_msg.substring(ret_msg.indexOf('(')+1, ret_msg.indexOf(')')); + String[] tmpArray = ret_msg.split("[,]"); + + if(tmpArray.length <= 1) + return Integer.parseInt(tmpArray[0]); + else + return Integer.parseInt(tmpArray[4])*256 + Integer.parseInt(tmpArray[5]); + } + +//************************************************************************************** +//************************************************************************************** + + /** + * Keep the connection alive + */ + public void run(){ + try { + while(true){ + if(last_sent > System.currentTimeMillis() + FTP_NOOP_INT*1000){ + sendCommand("NOOP"); + } + try{ Thread.sleep(5000); }catch(Exception e){} + } + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + /** + * Close the FTP connection + */ + public void close() throws IOException{ + sendCommand("QUIT"); + in.close(); + out.close(); + socket.close(); + this.interrupt(); + } +} diff --git a/src/zutil/net/POP3Client.java b/src/zutil/net/POP3Client.java new file mode 100644 index 00000000..d1608458 --- /dev/null +++ b/src/zutil/net/POP3Client.java @@ -0,0 +1,340 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * A simple class that connects and logs in to a POP3 + * server and then can read and delete messages. + * INFO: http://pages.prodigy.net/michael_santovec/pop3telnet.htm + * + * @author Ziver + * + */ +public class POP3Client { + public static boolean DEBUG = false; + public static final int POP3_PORT = 110; + public static final int POP3_SSL_PORT = 995; + + private BufferedReader in; + private PrintStream out; + private Socket socket; + + /** + * Connect to a POP3 server without username + * + * @param host The hostname of the server + * @throws UnknownHostException + * @throws IOException + */ + public POP3Client(String host) throws UnknownHostException, IOException{ + this(host, POP3_PORT, null, null, false); + } + + /** + * Connect to a POP3 server with username and password + * + * @param host The hostname of the server + * @param user The username + * @param password the password + * @throws UnknownHostException + * @throws IOException + */ + public POP3Client(String host, String user, String password) throws UnknownHostException, IOException{ + this(host, POP3_PORT, user, password, false); + } + + /** + * Connects to a POP3 server with username and password and SSL + * + * @param host The hostname of the server + * @param user The username + * @param password the password + * @param ssl If SSL should be used + * @throws UnknownHostException + * @throws IOException + */ + public POP3Client(String host, String user, String password, boolean ssl) throws UnknownHostException, IOException{ + this(host, (ssl ? POP3_SSL_PORT : POP3_PORT), user, password, ssl); + } + + /** + * Connects to a POP3 server with username and password and + * SSL and with costume port. + * + * @param host The hostname of the server + * @param port The port number to connect to on the server + * @param user The username + * @param password the password + * @param ssl If SSL should be used + * @throws UnknownHostException + * @throws IOException + */ + public POP3Client(String host, int port, String user, String password, boolean ssl) throws UnknownHostException, IOException{ + if(ssl) connectSSL(host, port); + else connect(host, port); + + if(user != null){ + login(user, password); + } + } + + /** + * Connects to the server + * + * @param host The hostname of the server + * @param port The port to connect to on the server + * @throws UnknownHostException + * @throws IOException + */ + private void connect(String host, int port) throws UnknownHostException, IOException{ + socket = new Socket(host, port); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new PrintStream(socket.getOutputStream()); + + readCommand(true); + } + + /** + * Connects to the server with SSL. + * http://www.exampledepot.com/egs/javax.net.ssl/Client.html + * + * @param host The hostname of the server + * @param port The port to connect to on the server + * @throws UnknownHostException + * @throws IOException + */ + private void connectSSL(String host, int port) throws UnknownHostException, IOException{ + SocketFactory socketFactory = SSLSocketFactory.getDefault(); + socket = socketFactory.createSocket(host, port); + + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new PrintStream(socket.getOutputStream()); + + readCommand(DEBUG); + } + + /** + * Logs in to the POP3 server with the username and password if the password is set + * + * @param user The user name + * @param password The password or null if no password is required + * @throws IOException + */ + private void login(String user, String password) throws IOException{ + sendCommand("USER "+user); + if(password != null){ + sendNoReplyCommand("PASS "+password, false); + if(DEBUG)System.out.println("PASS ***"); + readCommand(DEBUG); + } + } + + /** + * Returns the number of messages that is on the server + * + * @return Message count + * @throws IOException + */ + public int getMessageCount() throws IOException{ + String msg = sendCommand("STAT", DEBUG); + return Integer.parseInt( + msg.substring( + msg.indexOf(' ')+1, + msg.indexOf(' ', msg.indexOf(' ')+1))); + } + + /** + * Retrieves the message with the given id. + * + * @param id The id of the message to get + * @return The message + * @throws IOException + */ + public String getMessage(int id) throws IOException{ + sendCommand("RETR "+id); + return readMultipleLines(DEBUG); + } + + /** + * Returns the title of the message + * + * @param id The message id + * @return The title + * @throws IOException + */ + public String getMessageTitle(int id) throws IOException{ + String tmp = getMessageHeader(id); + String tmp2 = tmp.toLowerCase(); + if(tmp2.contains("subject:")){ + return tmp.substring( + tmp2.indexOf("subject:")+8, + tmp2.indexOf('\n', + tmp2.indexOf("subject:"))); + } + else + return null; + } + + /** + * Returns the header of the given message id. + * + * @param id The id of the message to get + * @return The message + * @throws IOException + */ + public String getMessageHeader(int id) throws IOException{ + sendCommand("TOP "+id+" 0"); + return readMultipleLines(DEBUG); + } + + /** + * Deletes the message with the given id + * + * @param id The id of the message to be deleted + * @throws IOException + */ + public void delete(int id) throws IOException{ + sendCommand("DELE "+id); + } + + +//*********************** IO Stuff ********************************************* + + /** + * Sends the given line to the server and returns a status integer + * + * @param cmd The command to send + * @return The return code from the server + * @throws IOException if the cmd fails + */ + private boolean sendCommand(String cmd) throws IOException{ + return parseReturnCode(sendCommand(cmd, DEBUG)); + } + + /** + * Sends the given line to the server and returns the last line + * + * @param cmd The command to send + * @param print To print out the received lines + * @return Last String line from the server + * @throws IOException + */ + private String sendCommand(String cmd, boolean print) throws IOException{ + sendNoReplyCommand(cmd, print); + return readCommand(print); + } + + /** + * Sends a given command and don't cares about the reply + * + * @param cmd The command + * @param print If it should print to System.out + * @throws IOException + */ + private void sendNoReplyCommand(String cmd, boolean print) throws IOException{ + out.println(cmd); + if(print)System.out.println(cmd); + } + + /** + * Reads on line from the command channel + * + * @param print If the method should print the input line + * @return The input line + * @throws IOException if the server returns a error code + */ + private String readCommand(boolean print) throws IOException{ + String tmp = in.readLine(); + if(print)System.out.println(tmp); + if( !parseReturnCode(tmp) ) throw new IOException(tmp); + + return tmp; + } + + /** + * Reads from the server until there are a line with + * only one '.' + * + * @param print To print out the received lines + * @return String with the text + * @throws IOException + */ + private String readMultipleLines(boolean print) throws IOException{ + StringBuffer msg = new StringBuffer(); + String tmp = in.readLine(); + while(!tmp.equals(".")){ + msg.append(tmp); + msg.append('\n'); + tmp = in.readLine(); + if(print)System.out.println(tmp); + } + + return msg.toString(); + } + + + /** + * Parses the return line from the server and returns the status code + * + * @param msg The message from the server + * @return Returns true if return code is OK false if it is ERR + * @throws IOException + */ + private boolean parseReturnCode(String msg){ + int endpos = (msg.indexOf(' ')<0 ? msg.length() : msg.indexOf(' ')); + return msg.substring(0, endpos).equals("+OK"); + } + +//********************************************************************************* + + /** + * All the delete marked messages are unmarkt + * @throws IOException + */ + public void reset() throws IOException{ + sendCommand("RSET", DEBUG); + } + + /** + * All the changes(DELETE) are performed and then the connection is closed + * + * @throws IOException + */ + public void close() throws IOException{ + sendCommand("QUIT", DEBUG); + in.close(); + out.close(); + socket.close(); + } +} diff --git a/src/zutil/net/SMTPClient.java b/src/zutil/net/SMTPClient.java new file mode 100644 index 00000000..02062862 --- /dev/null +++ b/src/zutil/net/SMTPClient.java @@ -0,0 +1,178 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.Date; + +/** + * A simple class that connects and logs in to a SMTP + * server and then send emails. + * INFO: http://cr.yp.to/smtp/client.html + * + * @author Ziver + * + */ +public class SMTPClient { + public static boolean DEBUG = false; + + private BufferedReader in; + private PrintStream out; + private Socket socket; + private String url; + private int port; + + public SMTPClient(String url){ + this(url, 25); + } + + public SMTPClient(String url, int port){ + this.url = url; + this.port = port; + } + + /** + * Connects to the server. + * Sends the message. + * Closes the connection + * + * @param from The destination email address + * @param to The recipients email address + * @param subj The subject of the message + * @param msg The message + * @throws IOException + */ + public synchronized void send(String from, String to, String subj, String msg) throws IOException{ + try{ + connect(); + // FROM and TO + sendCommand("MAIL FROM:"+from); + sendCommand("RCPT TO:"+to); + sendCommand("DATA"); + // The Message + sendNoReplyCommand("Date: "+(new Date()), DEBUG); + sendNoReplyCommand("From: "+from, DEBUG); + sendNoReplyCommand("To: "+to, DEBUG); + sendNoReplyCommand("Subject: "+subj, DEBUG); + sendNoReplyCommand(" ", DEBUG); + sendNoReplyCommand(msg, DEBUG); + sendCommand(".", DEBUG); + + close(); + }catch(IOException e){ + close(); + throw e; + } + } + + /** + * Connects to the server + * + * @throws UnknownHostException + * @throws IOException + */ + public void connect() throws UnknownHostException, IOException{ + socket = new Socket(url, port); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new PrintStream(socket.getOutputStream()); + + readCommand(DEBUG); + sendCommand("HELO "+url); + } + + /** + * Sends the given line to the server and returns a status integer + * + * @param cmd The command to send + * @return The return code from the server + * @throws IOException if the cmd fails + */ + private int sendCommand(String cmd) throws IOException{ + return parseReturnCode(sendCommand(cmd, DEBUG)); + } + + /** + * Sends the given line to the server and returns the last line + * + * @param cmd The command to send + * @param print To print out the received lines + * @return Last String line from the server + * @throws IOException + */ + private String sendCommand(String cmd, boolean print) throws IOException{ + sendNoReplyCommand(cmd, print); + return readCommand(print); + } + + /** + * Sends a given command and don't cares about the reply + * + * @param cmd The command + * @param print If it should print to System.out + * @throws IOException + */ + private void sendNoReplyCommand(String cmd, boolean print) throws IOException{ + out.println(cmd); + if(print)System.out.println(cmd); + } + + /** + * Reads on line from the command channel + * + * @param print If the method should print the input line + * @return The input line + * @throws IOException if the server returns a error code + */ + private String readCommand(boolean print) throws IOException{ + String tmp = in.readLine(); + if(print)System.out.println(tmp); + if(parseReturnCode(tmp) >= 400 ) throw new IOException(tmp); + + return tmp; + } + + /** + * Parses the return line from the server and returns the status code + * + * @param msg The message from the server + * @return The status code + * @throws IOException + */ + private synchronized int parseReturnCode(String msg){ + return Integer.parseInt(msg.substring(0, 3)); + } + + public void close() throws IOException{ + sendCommand("QUIT", DEBUG); + in.close(); + out.close(); + socket.close(); + } +} diff --git a/src/zutil/net/ServerFind.java b/src/zutil/net/ServerFind.java new file mode 100644 index 00000000..1893a63f --- /dev/null +++ b/src/zutil/net/ServerFind.java @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +import zutil.io.MultiPrintStream; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.MulticastSocket; + +/** + * This class broadcast its address in the LAN so that + * the ServerFindClient can get the server IP + * + * @author Ziver + * + */ +public class ServerFind extends Thread { + public String broadcastAddress = "230.0.0.1"; + + private InetAddress group; + private MulticastSocket Msocket; + + private boolean avsluta; + private int port; + + /** + * Creates a ServerFind Thread an the specified port + * + * @param port The port to run the ServerFind Server on + * @throws IOException + */ + public ServerFind (int port) throws IOException { + this.port = port; + avsluta = false; + group = InetAddress.getByName(broadcastAddress); + Msocket = new MulticastSocket(port); + Msocket.joinGroup(group); + + start(); + } + + public void run (){ + byte[] buf = new byte[256]; + DatagramPacket packet; + DatagramSocket lan_socket = null; + + while (!avsluta){ + try { + packet = new DatagramPacket(buf, buf.length); + Msocket.receive(packet); + + lan_socket = new DatagramSocket(port , packet.getAddress()); + packet = new DatagramPacket(buf, buf.length, group, port); + lan_socket.send(packet); + lan_socket.close(); + } catch (Exception e) { + MultiPrintStream.out.println("Error Establishing ServerFind Connection!!!\n" + e); + e.printStackTrace(); + } + } + + close(); + } + + /** + * Closes the broadcast socket + */ + public void close(){ + avsluta = true; + Msocket.close(); + } +} diff --git a/src/zutil/net/ServerFindClient.java b/src/zutil/net/ServerFindClient.java new file mode 100644 index 00000000..bee2a531 --- /dev/null +++ b/src/zutil/net/ServerFindClient.java @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.MulticastSocket; + +/** + * This class is the client for ServerFind that receives the server IP + * + * @author Ziver + * + */ +public class ServerFindClient{ + public String broadcastAddress = "230.0.0.1"; + + private int port; + + /** + * Creates a ServerFind Client + * + * @param port The port to contact the server on + */ + public ServerFindClient(int port){ + this.port = port; + } + + /** + * Requests IP from server + * + * @return The address of the server + * @throws IOException + */ + public InetAddress find() throws IOException{ + InetAddress group = InetAddress.getByName(broadcastAddress); + DatagramSocket lan_socket = new DatagramSocket(); + MulticastSocket Msocket = new MulticastSocket(port); + Msocket.joinGroup(group); + + byte[] buf = new byte[256]; + DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port); + lan_socket.send(packet); + + packet = new DatagramPacket(buf, buf.length); + Msocket.receive(packet); + + return packet.getAddress(); + } +} diff --git a/src/zutil/net/ThroughputCalculator.java b/src/zutil/net/ThroughputCalculator.java new file mode 100644 index 00000000..1464af93 --- /dev/null +++ b/src/zutil/net/ThroughputCalculator.java @@ -0,0 +1,75 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +/** + * Created by Ziver Koc + */ +public class ThroughputCalculator { + public static final float UPDATES_PER_SEC = 1; + public static final double NANOSEC_PER_SECOND = 1000000000.0; + + private boolean updated; + private double throughput; + private long previousTimeStamp; + private long data_amount; + private long total_data_amount; + private float frequency = UPDATES_PER_SEC; + + public void setTotalHandledData(long bytes){ + setHandledData(bytes - total_data_amount); + total_data_amount = bytes; + } + public void setHandledData(long bytes){ + long currentTimeStamp = System.nanoTime(); + data_amount += bytes; + if(currentTimeStamp - (NANOSEC_PER_SECOND/frequency) > previousTimeStamp) { + throughput = data_amount / ((currentTimeStamp - previousTimeStamp) / NANOSEC_PER_SECOND); + previousTimeStamp = currentTimeStamp; + data_amount = 0; + updated = true; + } + } + + public double getByteThroughput(){ + setHandledData(0); // Update throughput + updated = false; + return throughput; + } + public double getBitThroughput(){ + return getByteThroughput()*8; + } + + public boolean isUpdated(){ + return updated; + } + + public void setFrequency(float frequency) { + if(frequency < 0) + this.frequency = UPDATES_PER_SEC; + else + this.frequency = frequency; + } +} diff --git a/src/zutil/net/dns/DNSPacket.java b/src/zutil/net/dns/DNSPacket.java new file mode 100755 index 00000000..2cef175e --- /dev/null +++ b/src/zutil/net/dns/DNSPacket.java @@ -0,0 +1,246 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.dns; + +import zutil.parser.binary.BinaryStruct; + +/** + * Created by Ziver on 2016-02-09. + * Reference: http://tools.ietf.org/html/rfc1035 + */ +public class DNSPacket implements BinaryStruct { + public static final int OPCODE_QUERY = 0; + public static final int OPCODE_IQUERY = 1; + public static final int OPCODE_STATUS = 2; + + public static final int RCODE_NO_ERROR = 0; + public static final int RCODE_FORMAT_ERROR = 1; + public static final int RCODE_SERVER_FAILURE = 2; + public static final int RCODE_NAME_ERROR = 3; + public static final int RCODE_NOT_IMPLEMENTED = 4; + public static final int RCODE_REFUSED = 5; + + + @BinaryField(index=0, length=16) + int id; + + //////////////// FLAGS + //@BinaryField(index=10, length=16) + //int flags; + /** + * A one bit field that specifies whether this message is a + * query (0), or a response (1). + */ + @BinaryField(index=10, length=1) + boolean flagQueryResponse; + /** + * A four bit field that specifies kind of query in this message. + *
    +     * 0    a standard query (QUERY)
    +     * 1    an inverse query (IQUERY)
    +     * 2    a server status request (STATUS)
    +     * 
    + */ + @BinaryField(index=11, length=4) + int flagOperationCode; + /** + * This bit is valid in responses, + * and specifies that the responding name server is an + * authority for the domain name in question section. + */ + @BinaryField(index=12, length=1) + boolean flagAuthoritativeAnswer; + /** + * specifies that this message was truncated + * due to length greater than that permitted on the + * transmission channel. + */ + @BinaryField(index=13, length=1) + boolean flagTruncation; + /** + * this bit may be set in a query and + * is copied into the response. If RD is set, it directs + * the name server to pursue the query recursively. + * Recursive query support is optional. + */ + @BinaryField(index=14, length=1) + boolean flagRecursionDesired; + /** + * this be is set or cleared in a + * response, and denotes whether recursive query support is + * available in the name server. + */ + @BinaryField(index=15, length=1) + boolean flagRecursionAvailable; + /** + * Reserved for future use. Must be zero in all queries + * and responses. + */ + @BinaryField(index=16, length=3) + private int z; + /** + * this field is set as part of responses. + * The values have the following interpretation: + *
    +     * 0    No error condition
    +     * 1    Format error - The name server was
    +     *      unable to interpret the query.
    +     * 2    Server failure - The name server was
    +     *      unable to process this query due to a
    +     *      problem with the name server.
    +     * 3    Name Error - Meaningful only for
    +     *      responses from an authoritative name
    +     *      server, this code signifies that the
    +     *      domain name referenced in the query does
    +     *      not exist.
    +     * 4    Not Implemented - The name server does
    +     *      not support the requested kind of query.
    +     * 5    Refused - The name server refuses to
    +     *      perform the specified operation for
    +     *      policy reasons.
    +     *
    + */ + @BinaryField(index=17, length=4) + int flagResponseCode; + + + //////////////// COUNTS + /** + * Question Count. + * Specifying the number of entries in the question section. + */ + @BinaryField(index=20, length=16) + int countQuestion; + /** + * Answer Record Count. + * specifying the number of resource records in + * the answer section. + */ + @BinaryField(index=21, length=16) + int countAnswerRecord; + /** + * Name Server (Authority Record) Count. + * Specifying the number of name server resource records + * in the authority records section. + */ + @BinaryField(index=22, length=16) + int countNameServer; + /** + * Additional Record Count. + * Specifying the number of resource records in the + * additional records section + */ + @BinaryField(index=23, length=16) + int countAdditionalRecord; + + + + /* + Question section format + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / QNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QTYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QCLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + where: + + QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. + + QTYPE a two octet code which specifies the type of the query. + The values for this field include all codes valid for a + TYPE field, together with some more general codes which + can match more than one type of RR. + + QCLASS a two octet code that specifies the class of the query. + For example, the QCLASS field is IN for the Internet. + */ + + /* + Resource record format + + The answer, authority, and additional sections all share the same + format: a variable number of resource records, where the number of + records is specified in the corresponding count field in the header. + Each resource record has the following format: + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + where: + + NAME a domain name to which this resource record pertains. + + TYPE two octets containing one of the RR type codes. This + field specifies the meaning of the data in the RDATA + field. + + CLASS two octets which specify the class of the data in the + RDATA field. + + TTL a 32 bit unsigned integer that specifies the time + interval (in seconds) that the resource record may be + cached before it should be discarded. Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached. + + RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + + RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + For example, the if the TYPE is A and the CLASS is IN, + the RDATA field is a 4 octet ARPA Internet address. + */ +} diff --git a/src/zutil/net/dns/MulticastDNSClient.java b/src/zutil/net/dns/MulticastDNSClient.java new file mode 100755 index 00000000..49f79bb3 --- /dev/null +++ b/src/zutil/net/dns/MulticastDNSClient.java @@ -0,0 +1,77 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.dns; + +import zutil.net.threaded.ThreadedUDPNetwork; +import zutil.net.threaded.ThreadedUDPNetworkThread; +import zutil.parser.binary.BinaryStructInputStream; +import zutil.parser.binary.BinaryStructOutputStream; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Created by Ziver + */ +public class MulticastDNSClient extends ThreadedUDPNetwork implements ThreadedUDPNetworkThread{ + private static final String MDNS_MULTICAST_ADDR = "224.0.0.251"; + private static final int MDNS_MULTICAST_PORT = 5353; + + + public MulticastDNSClient() throws IOException { + super(null, MDNS_MULTICAST_ADDR, MDNS_MULTICAST_PORT); + setThread( this ); + } + + + public void sendProbe() { + try { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + BinaryStructOutputStream out = new BinaryStructOutputStream(buffer); + + DNSPacket header = new DNSPacket(); + out.write(header); + + DatagramPacket packet = null; + + packet = new DatagramPacket( + buffer.toByteArray(), buffer.size(), + InetAddress.getByName( MDNS_MULTICAST_ADDR ), + MDNS_MULTICAST_PORT ); + send(packet); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) { + DNSPacket header = new DNSPacket(); + int length = BinaryStructInputStream.parse(header, packet.getData()); + } +} diff --git a/src/zutil/net/http/HttpClient.java b/src/zutil/net/http/HttpClient.java new file mode 100755 index 00000000..1cb39a77 --- /dev/null +++ b/src/zutil/net/http/HttpClient.java @@ -0,0 +1,151 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import zutil.net.http.HttpPrintStream.HttpMessageType; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Socket; +import java.net.URL; +import java.util.HashMap; + +/** + * This class connects to a HTTP server and + * parses the result + * + * @author Ziver + */ +public class HttpClient implements AutoCloseable{ + public static enum HttpRequestType{ + GET, POST + } + + // Request variables + private HttpURL url; + private HttpRequestType type; + private HashMap headers; + private HashMap cookies; + private String data; + + // Response variables + private HttpHeaderParser rspHeader; + private BufferedReader rspReader; + + + + public HttpClient(HttpRequestType type){ + this.type = type; + headers = new HashMap(); + cookies = new HashMap(); + } + + + public void setURL( URL url){ + this.url = new HttpURL( url ); + } + + /** + * Adds a parameter to the request + */ + public void setParameter( String key, String value ){ + url.setParameter(key, value); + } + + /** + * Adds a cookie to the request + */ + public void setCookie( String key, String value ){ + cookies.put(key, value); + } + + /** + * Adds a header value to the request + */ + public void setHeader( String key, String value ){ + headers.put(key, value); + } + + /** + * Sets the content data that will be included in the request. + * NOTE: this will override the POST data parameter inclusion. + */ + public void setData( String data ){ + this.data = data; + } + + /** + * Will send a HTTP request to the target host. + * NOTE: any previous request connections will be closed + */ + public HttpHeaderParser send() throws IOException{ + Socket conn = new Socket( url.getHost(), url.getPort()); + + // Request + HttpPrintStream request = new HttpPrintStream( conn.getOutputStream(), HttpMessageType.REQUEST ); + request.setRequestType( type.toString() ); + request.setRequestURL( url.getHttpURL() ); + request.setHeaders( headers ); + request.setCookies( cookies ); + + if( type == HttpRequestType.POST ){ + String postData = null; + if(data != null) + postData = data; + else + postData = url.getParameterString(); + request.setHeader("Content-Length", ""+postData.length()); + request.println(); + request.print( postData ); + } + else + request.println(); + request.close(); + + // Response + if(rspHeader != null || rspReader != null) // Close previous request + this.close(); + rspReader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + rspHeader = new HttpHeaderParser( rspReader ); + + return rspHeader; + } + + public HttpHeaderParser getResponseHeader(){ + return rspHeader; + } + public BufferedReader getResponseReader(){ + return rspReader; + } + + @Override + public void close() throws IOException { + if(rspReader != null) + rspReader.close(); + rspReader = null; + rspHeader = null; + } +} diff --git a/src/zutil/net/http/HttpHeader.java b/src/zutil/net/http/HttpHeader.java new file mode 100755 index 00000000..c0626849 --- /dev/null +++ b/src/zutil/net/http/HttpHeader.java @@ -0,0 +1,176 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import zutil.converter.Converter; + +import java.util.HashMap; +import java.util.Iterator; + +public class HttpHeader { + // HTTP info + private String type; + private String url; + private HashMap urlAttributes; + private float version; + private int httpCode; + + // Parameters + private HashMap headers; + private HashMap cookies; + + + protected HttpHeader(){ + urlAttributes = new HashMap(); + headers = new HashMap(); + cookies = new HashMap(); + } + + + /** + * @return the HTTP message type( ex. GET,POST...) + */ + public String getRequestType(){ + return type; + } + /** + * @return the HTTP version of this header + */ + public float getHTTPVersion(){ + return version; + } + /** + * @return the HTTP Return Code from a Server + */ + public int getHTTPCode(){ + return httpCode; + } + /** + * @return the URL that the client sent the server + */ + public String getRequestURL(){ + return url; + } + /** + * @return a Iterator with all defined url keys + */ + public Iterator getURLAttributeKeys(){ + return urlAttributes.keySet().iterator(); + } + /** + * Returns the URL attribute value of the given name. + * + * returns null if there is no such attribute + */ + public String getURLAttribute(String name){ + return urlAttributes.get( name ); + } + /** + * @return a Iterator with all defined headers + */ + public Iterator getHeaderKeys(){ + return headers.keySet().iterator(); + } + /** + * Returns the HTTP attribute value of the given name. + * + * returns null if there is no such attribute + */ + public String getHeader(String name){ + return headers.get( name.toUpperCase() ); + } + /** + * @return a Iterator with all defined cookies + */ + public Iterator getCookieKeys(){ + return cookies.keySet().iterator(); + } + /** + * Returns the cookie value of the given name. + * + * returns null if there is no such attribute + */ + public String getCookie(String name){ + return cookies.get( name ); + } + + + protected HashMap getCookieMap(){ + return cookies; + } + protected HashMap getUrlAttributeMap(){ + return urlAttributes; + } + + protected void setRequestType(String type){ + this.type = type.trim(); + } + protected void setHTTPVersion(float version){ + this.version = version; + } + protected void setHTTPCode(int code){ + this.httpCode = code; + } + protected void setRequestURL(String url){ + this.url = url.trim().replaceAll("//", "/"); + } + protected void putCookie(String key, String value){ + cookies.put(key.trim(), value.trim()); + } + protected void putURLAttribute(String key, String value){ + urlAttributes.put(key.trim(), value.trim()); + } + protected void putHeader(String key, String value){ + headers.put(key.trim(), value.trim()); + } + + + + public String toString(){ + StringBuilder tmp = new StringBuilder(); + tmp.append("{Type: ").append(type); + tmp.append(", HTTP_version: HTTP/").append(version); + if(url == null) + tmp.append(", URL: null"); + else + tmp.append(", URL: \"").append(url).append('\"'); + + tmp.append(", URL_attr: ").append(toStringAttributes()); + tmp.append(", Headers: ").append(toStringHeaders()); + tmp.append(", Cookies: ").append(toStringCookies()); + + tmp.append('}'); + return tmp.toString(); + } + public String toStringHeaders(){ + return Converter.toString(headers); + } + public String toStringCookies(){ + return Converter.toString(cookies); + } + public String toStringAttributes(){ + return Converter.toString(urlAttributes); + } +} diff --git a/src/zutil/net/http/HttpHeaderParser.java b/src/zutil/net/http/HttpHeaderParser.java new file mode 100755 index 00000000..82c8a19e --- /dev/null +++ b/src/zutil/net/http/HttpHeaderParser.java @@ -0,0 +1,158 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import zutil.parser.URLDecoder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.regex.Pattern; + +public class HttpHeaderParser { + public static final String HEADER_COOKIE = "COOKIE"; + + private static final Pattern PATTERN_COLON = Pattern.compile(":"); + private static final Pattern PATTERN_EQUAL = Pattern.compile("="); + private static final Pattern PATTERN_AND = Pattern.compile("&"); + private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); + + + private BufferedReader in; + + + /** + * Parses the HTTP header information from a stream + * + * @param in is the stream + */ + public HttpHeaderParser(BufferedReader in){ + this.in = in; + } + + /** + * Parses the HTTP header information from a String + * + * @param in is the String + */ + public HttpHeaderParser(String in){ + this.in = new BufferedReader(new StringReader(in)); + } + + + public HttpHeader read() throws IOException { + HttpHeader header = null; + String line = null; + if( (line=in.readLine()) != null && !line.isEmpty() ){ + header = new HttpHeader(); + parseStatusLine(header, line); + while( (line=in.readLine()) != null && !line.isEmpty() ){ + parseLine(header, line); + } + parseCookies(header); + } + return header; + } + + + /** + * Parses the first header line and ads the values to + * the map and returns the file name and path + * + * @param line The header String + * @return The path and file name as a String + */ + protected static void parseStatusLine(HttpHeader header, String line){ + // Server Response + if( line.startsWith("HTTP/") ){ + header.setHTTPVersion( Float.parseFloat( line.substring( 5 , 8))); + header.setHTTPCode( Integer.parseInt( line.substring( 9, 12 ))); + } + // Client Request + else if(line.contains("HTTP/")){ + header.setRequestType( line.substring(0, line.indexOf(" "))); + header.setHTTPVersion( Float.parseFloat( line.substring(line.lastIndexOf("HTTP/")+5 , line.length()).trim())); + line = (line.substring(header.getRequestType().length()+1, line.lastIndexOf("HTTP/"))); + + // parse URL and attributes + int index = line.indexOf('?'); + if(index > -1){ + header.setRequestURL( line.substring(0, index)); + line = line.substring( index+1, line.length()); + parseURLParameters(header, line); + } + else{ + header.setRequestURL(line); + } + } + } + + /** + * Parses the rest of the header + * + * @param line is the next line in the header + */ + protected void parseLine(HttpHeader header, String line){ + String[] data = PATTERN_COLON.split( line, 2 ); + header.putHeader( + data[0].trim().toUpperCase(), // Key + (data.length>1 ? data[1] : "").trim()); //Value + } + + /** + * Parses the header "Cookie" and stores all cookies in the HttpHeader object + */ + protected void parseCookies(HttpHeader header){ + String cookieHeader = header.getHeader(HEADER_COOKIE); + if(cookieHeader != null && !cookieHeader.isEmpty()){ + String[] tmp = PATTERN_SEMICOLON.split(cookieHeader); + for(String cookie : tmp){ + String[] tmp2 = PATTERN_EQUAL.split(cookie, 2); + header.putCookie( + tmp2[0].trim(), // Key + (tmp2.length>1 ? tmp2[1] : "").trim()); //Value + } + } + } + + /** + * Parses a String with variables from a get or post + * that was sent from a client + * + * @param attributes is the String containing all the attributes + */ + protected static void parseURLParameters(HttpHeader header, String attributes){ + String[] tmp; + attributes = URLDecoder.decode(attributes); + // get the variables + String[] data = PATTERN_AND.split( attributes ); + for(String element : data){ + tmp = PATTERN_EQUAL.split(element, 2); + header.putURLAttribute( + tmp[0].trim(), // Key + (tmp.length>1 ? tmp[1] : "").trim()); //Value + } + } +} diff --git a/src/zutil/net/http/HttpPage.java b/src/zutil/net/http/HttpPage.java new file mode 100755 index 00000000..84f7286c --- /dev/null +++ b/src/zutil/net/http/HttpPage.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import java.io.IOException; +import java.util.Map; + +/** + * This is a interface for a ordinary page for the HttpServer + * + * @author Ziver + * + */ +public interface HttpPage{ + /** + * This method has to be implemented for every page. + * This method is called when a client wants a response + * from this specific page. + * + * @param out is a output stream to the client + * @param headers is the header received from the client + * @param session is the session associated with the current client + * @param cookie is cookie information from the client + * @param request is POST and GET requests from the client + */ + public abstract void respond(HttpPrintStream out, + HttpHeader headers, + Map session, + Map cookie, + Map request) throws IOException; +} diff --git a/src/zutil/net/http/HttpPrintStream.java b/src/zutil/net/http/HttpPrintStream.java new file mode 100755 index 00000000..74dec8b4 --- /dev/null +++ b/src/zutil/net/http/HttpPrintStream.java @@ -0,0 +1,348 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import zutil.converter.Converter; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.HashMap; + +/** + * This PrintStream is written for HTTP use + * It has buffer capabilities and cookie management. + * + * @author Ziver + * + */ +public class HttpPrintStream extends OutputStream{ + // Defines the type of message + public enum HttpMessageType{ + REQUEST, + RESPONSE + } + + // The actual output stream + private PrintStream out; + // This defines the type of message that will be generated + private HttpMessageType message_type; + // The status code of the message, ONLY for response + private Integer res_status_code; + // The request type of the message ONLY for request + private String req_type; + // The requesting url ONLY for request + private String req_url; + // An Map of all the header values + private HashMap headers; + // An Map of all the cookies + private HashMap cookies; + // The buffered header + private StringBuffer buffer; + // If the header buffering is enabled + private boolean buffer_enabled; + + /** + * Creates an new instance of HttpPrintStream with + * message type of RESPONSE and buffering disabled. + * + * @param out is the OutputStream where the data will be written to + */ + public HttpPrintStream(OutputStream out) { + this( out, HttpMessageType.RESPONSE ); + } + /** + * Creates an new instance of HttpPrintStream with + * message type buffering disabled. + * + * @param out is the OutputStream where the data will be written to + * @param type is the type of message + */ + public HttpPrintStream(OutputStream out, HttpMessageType type) { + this.out = new PrintStream(out); + this.message_type = type; + this.res_status_code = 0; + this.headers = new HashMap(); + this.cookies = new HashMap(); + this.buffer = new StringBuffer(); + this.buffer_enabled = false; + } + + /** + * Enable the buffering capability of the PrintStream. + * Nothing will be sent to the client when buffering + * is enabled until you close or flush the stream. + * This function will flush the stream if buffering is + * disabled. + * + * @param b + */ + public void enableBuffering(boolean b) throws IOException { + buffer_enabled = b; + if(!buffer_enabled) flush(); + } + + /** + * Adds a cookie that will be sent to the client + * + * @param key is the name of the cookie + * @param value is the value of the cookie + * @throws IOException if the header has already been sent + */ + public void setCookie(String key, String value) throws IOException{ + if(cookies == null) + throw new IOException("Header already sent!"); + cookies.put(key, value); + } + + /** + * Adds an header value + * + * @param key is the header name + * @param value is the value of the header + * @throws IOException if the header has already been sent + */ + public void setHeader(String key, String value) throws IOException{ + if(headers == null) + throw new IOException("Header already sent!"); + headers.put(key, value); + } + + /** + * Sets the status code of the message, ONLY available in HTTP RESPONSE + * + * @param code the code from 100 up to 599 + * @throws IOException if the header has already been sent or the message type is wrong + */ + public void setStatusCode(int code) throws IOException{ + if( res_status_code == null ) + throw new IOException("Header already sent!"); + if( message_type != HttpMessageType.RESPONSE ) + throw new IOException("Status Code is only available in HTTP RESPONSE!"); + res_status_code = code; + } + + /** + * Sets the request type of the message, ONLY available in HTTP REQUEST + * + * @param req_type is the type of the message, e.g. GET, POST... + * @throws IOException if the header has already been sent or the message type is wrong + */ + public void setRequestType(String req_type) throws IOException{ + if( req_type == null ) + throw new IOException("Header already sent!"); + if( message_type != HttpMessageType.REQUEST ) + throw new IOException("Request Message Type is only available in HTTP REQUEST!"); + this.req_type = req_type; + } + /** + * Sets the requesting URL of the message, ONLY available in HTTP REQUEST + * + * @param req_url is the URL + * @throws IOException if the header has already been sent or the message type is wrong + */ + public void setRequestURL(String req_url) throws IOException{ + if( req_url == null ) + throw new IOException("Header already sent!"); + if( message_type != HttpMessageType.REQUEST ) + throw new IOException("Request URL is only available in HTTP REQUEST!"); + this.req_url = req_url; + } + + protected void setHeaders( HashMap map ){ + headers = map; + } + protected void setCookies( HashMap map ){ + cookies = map; + } + + + /** + * Prints a new line + */ + public void println() throws IOException { + printOrBuffer(System.lineSeparator()); + } + /** + * Prints with a new line + */ + public void println(String s) throws IOException { + printOrBuffer(s + System.lineSeparator()); + } + /** + * Prints an string + */ + public void print(String s) throws IOException { + printOrBuffer(s); + } + + /** + * Will buffer String or directly output headers if needed and then the String + */ + private void printOrBuffer(String s) throws IOException { + if(buffer_enabled){ + buffer.append(s); + } + else{ + if(res_status_code != null){ + if( message_type==HttpMessageType.REQUEST ) + out.print(req_type + " " + req_url + " HTTP/1.0"); + else + out.print("HTTP/1.0 " + res_status_code + " " + getStatusString(res_status_code)); + out.println(); + res_status_code = null; + req_type = null; + req_url = null; + } + if(headers != null){ + for(String key : headers.keySet()){ + out.println(key + ": " + headers.get(key)); + } + headers = null; + } + if(cookies != null){ + if( !cookies.isEmpty() ){ + if( message_type==HttpMessageType.REQUEST ){ + out.print("Cookie: "); + for(String key : cookies.keySet()){ + out.print(key + "=" + cookies.get(key) + "; "); + } + out.println(); + } + else{ + for(String key : cookies.keySet()){ + out.print("Set-Cookie: " + key + "=" + cookies.get(key) + ";"); + out.print(System.lineSeparator()); + } + } + } + out.print(System.lineSeparator()); + cookies = null; + } + out.print(s); + } + } + + /** + * @return if headers has been sent. The setHeader, setStatusCode, setCookie method will throw Exceptions + */ + public boolean isHeaderSent() { + return res_status_code == null && headers == null && cookies == null; + } + + + /** + * Sends out the buffer and clears it + */ + @Override + public void flush() throws IOException { + flushBuffer(); + out.flush(); + } + + @Override + public void close() throws IOException { + flush(); + out.close(); + } + + protected void flushBuffer() throws IOException { + if(buffer_enabled){ + buffer_enabled = false; + printOrBuffer(buffer.toString()); + buffer.delete(0, buffer.length()); + buffer_enabled = true; + } + else if(res_status_code != null || headers != null || cookies != null){ + printOrBuffer(""); + } + } + + /** + * Will flush all buffers and write binary data to stream + */ + @Override + public void write(int b) throws IOException { + flushBuffer(); + out.write(b); + } + /** + * * Will flush all buffers and write binary data to stream + */ + @Override + public void write(byte[] buf, int off, int len) throws IOException { + flushBuffer(); + out.write(buf, off, len); + } + + private void rawWrite(String s) throws IOException { + out.write(s.getBytes()); + } + + private String getStatusString(int type){ + switch(type){ + case 100: return "Continue"; + case 200: return "OK"; + case 301: return "Moved Permanently"; + case 307: return "Temporary Redirect"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + default: return ""; + } + } + + public String toString() { + StringBuilder str = new StringBuilder(); + str.append("{http_type: ").append(message_type); + if (res_status_code != null) { + if (message_type == HttpMessageType.REQUEST) { + str.append(", req_type: ").append(req_type); + if(req_url == null) + str.append(", req_url: null"); + else + str.append(", req_url: \"").append(req_url).append('\"'); + } else if (message_type == HttpMessageType.RESPONSE){ + str.append(", status_code: ").append(res_status_code); + str.append(", status_str: ").append(getStatusString(res_status_code)); + } + + if (headers != null) { + str.append(", Headers: ").append(Converter.toString(headers)); + } + if (cookies != null) { + str.append(", Cookies: ").append(Converter.toString(cookies)); + } + } + else + str.append(", HEADER ALREADY SENT "); + str.append('}'); + + return str.toString(); + } +} diff --git a/src/zutil/net/http/HttpServer.java b/src/zutil/net/http/HttpServer.java new file mode 100755 index 00000000..ab58876e --- /dev/null +++ b/src/zutil/net/http/HttpServer.java @@ -0,0 +1,298 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import zutil.StringUtil; +import zutil.log.LogUtil; +import zutil.net.threaded.ThreadedTCPNetworkServer; +import zutil.net.threaded.ThreadedTCPNetworkServerThread; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Socket; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * A simple web server that handles both cookies and + * sessions for all the clients + * + * @author Ziver + */ +public class HttpServer extends ThreadedTCPNetworkServer{ + private static final Logger logger = LogUtil.getLogger(); + + public static final String SESSION_ID_KEY = "session_id"; + public static final String SESSION_TTL_KEY = "session_ttl"; + public static final String SERVER_VERSION = "Ziver HttpServer 1.1"; + public static final int SESSION_TTL = 10*60*1000; // in milliseconds + + + private Map pages; + private HttpPage defaultPage; + private Map> sessions; + private int nextSessionId; + + /** + * Creates a new instance of the sever + * + * @param port The port that the server should listen to + */ + public HttpServer(int port){ + this(port, null, null); + } + + + /** + * Creates a new instance of the sever + * + * @param port The port that the server should listen to + * @param keyStore If this is not null then the server will use SSL connection with this keyStore file path + * @param keyStorePass If this is not null then the server will use a SSL connection with the given certificate + */ + public HttpServer(int port, File keyStore, String keyStorePass){ + super( port, keyStore, keyStorePass ); + + pages = new ConcurrentHashMap<>(); + sessions = new ConcurrentHashMap<>(); + nextSessionId = 0; + + Timer timer = new Timer(); + timer.schedule(new SessionGarbageCollector(), 10000, SESSION_TTL / 2); + + logger.info("HTTP"+(keyStore==null?"":"S")+" Server ready!"); + } + + /** + * This class acts as an garbage collector that + * removes old sessions from the session HashMap + * + * @author Ziver + */ + private class SessionGarbageCollector extends TimerTask { + public void run(){ + Object[] keys = sessions.keySet().toArray(); + for(Object key : keys){ + Map session = sessions.get(key); + + // Check if session is still valid + if((Long)session.get(SESSION_TTL_KEY) < System.currentTimeMillis()){ + sessions.remove(key); + logger.fine("Removing Session: "+key); + } + } + } + } + + /** + * Add a HttpPage to a specific URL + * + * @param name The URL or name of the page + * @param page The page itself + */ + public void setPage(String name, HttpPage page){ + if(name.charAt(0) != '/') + name = "/"+name; + pages.put(name, page); + } + + /** + * This is a default page that will be shown + * if there is no other matching page, + * + * @param page The HttpPage that will be shown + */ + public void setDefaultPage(HttpPage page){ + defaultPage = page; + } + + protected ThreadedTCPNetworkServerThread getThreadInstance( Socket s ){ + try { + return new HttpServerThread( s ); + } catch (IOException e) { + logger.log(Level.SEVERE, "Could not start new Thread", e); + } + return null; + } + + /** + * Internal class that handles all the requests + * + * @author Ziver + * + */ + protected class HttpServerThread implements ThreadedTCPNetworkServerThread{ + private HttpPrintStream out; + private BufferedReader in; + private Socket socket; + + public HttpServerThread(Socket socket) throws IOException{ + out = new HttpPrintStream(socket.getOutputStream()); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + this.socket = socket; + } + + public void run(){ + String tmp = null; + HttpHeaderParser headerParser = new HttpHeaderParser(in); + + //**************************** REQUEST ********************************* + try { + long time = System.currentTimeMillis(); + HttpHeader header = headerParser.read(); + if(header == null){ + logger.finer("No header received"); + return; + } + + //******* Read in the post data if available + if( header.getHeader("Content-Length") != null ){ + // Reads the post data size + tmp = header.getHeader("Content-Length"); + int post_data_length = Integer.parseInt( tmp ); + // read the data + StringBuilder tmpBuff = new StringBuilder(); + // read the data + for(int i=0; i session; + long ttlTime = System.currentTimeMillis() + SESSION_TTL; + String sessionCookie = header.getCookie(SESSION_ID_KEY); + if( sessionCookie != null && sessions.containsKey(sessionCookie) && + (Long)sessions.get(sessionCookie).get(SESSION_TTL_KEY) < System.currentTimeMillis()){ // Check if session is still valid + + session = sessions.get(sessionCookie); + // renew the session TTL + session.put(SESSION_TTL_KEY, ttlTime); + } + else{ + session = Collections.synchronizedMap(new HashMap()); + session.put(SESSION_ID_KEY, nextSessionId ); + session.put(SESSION_TTL_KEY, ttlTime ); + sessions.put(nextSessionId, session ); + ++nextSessionId; + } + + //**************************** RESPONSE ************************************ + out.setStatusCode(200); + out.setHeader("Server", SERVER_VERSION); + out.setHeader("Content-Type", "text/html"); + out.setCookie(SESSION_ID_KEY, ""+session.get(SESSION_ID_KEY)); + + if( header.getRequestURL() != null && pages.containsKey(header.getRequestURL())){ + HttpPage page = pages.get(header.getRequestURL()); + page.respond(out, header, session, header.getCookieMap(), header.getUrlAttributeMap()); + if(LogUtil.isLoggable(page.getClass(), Level.FINER)) + logRequest(header, session, time); + } + else if( header.getRequestURL() != null && defaultPage != null ){ + defaultPage.respond(out, header, session, header.getCookieMap(), header.getUrlAttributeMap()); + if(LogUtil.isLoggable(defaultPage.getClass(), Level.FINER)) + logRequest(header, session, time); + } + else{ + out.setStatusCode(404); + out.println("404 Page Not Found: "+header.getRequestURL()); + logger.warning("Page not defined: " + header.getRequestURL()); + } + + //******************************************************************************** + } catch (Exception e) { + logger.log(Level.SEVERE, "500 Internal Server Error", e); + try { + if (!out.isHeaderSent()) + out.setStatusCode(500); + if (e.getMessage() != null) + out.println("500 Internal Server Error: " + e.getMessage()); + else if (e.getCause() != null) { + out.println("500 Internal Server Error: " + e.getCause().getMessage()); + } else { + out.println("500 Internal Server Error: " + e); + } + }catch(IOException ioe){ + logger.log(Level.SEVERE, null, ioe); + } + } + finally { + try{ + out.close(); + in.close(); + socket.close(); + } catch( Exception e ) { + logger.log(Level.WARNING, "Could not close connection", e); + } + } + } + } + + + protected static void logRequest(HttpHeader header, + Map session, + long time){ + // Debug + if(logger.isLoggable(Level.FINEST) ){ + StringBuilder buff = new StringBuilder(); + buff.append("Received request: ").append(header.getRequestURL()); + buff.append(", ("); + buff.append("request: ").append(header.toStringAttributes()); + buff.append(", cookies: ").append(header.toStringCookies()); + buff.append(", session: ").append(session); + buff.append(")"); + buff.append(", time: "+ StringUtil.formatTimeToString(System.currentTimeMillis() - time)); + + logger.finer(buff.toString()); + } else if(logger.isLoggable(Level.FINER)){ + logger.finer( + "Received request: " + header.getRequestURL() + + ", time: "+ StringUtil.formatTimeToString(System.currentTimeMillis() - time)); + } + } +} diff --git a/src/zutil/net/http/HttpURL.java b/src/zutil/net/http/HttpURL.java new file mode 100644 index 00000000..f0929810 --- /dev/null +++ b/src/zutil/net/http/HttpURL.java @@ -0,0 +1,163 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import java.net.URL; +import java.util.HashMap; + +/** + * Handles URLs in the HTTP protocol + * + * @author Ziver + */ +public class HttpURL { + public static final String PROTOCOL_SEPARATOR = "://"; + public static final String PORT_SEPARATOR = ":"; + public static final String PATH_SEPARATOR = "/"; + public static final String PARAMETER_SEPARATOR = "?"; + public static final String ANCHOR_SEPARATOR = "#"; + + private String protocol = ""; + private String host = "127.0.0.1"; + private int port = -1; + private String path; + private String anchor; + + private HashMap parameters = new HashMap(); + + + public HttpURL(){} + + public HttpURL( URL url ){ + this.setProtocol( url.getProtocol() ); + this.setHost( url.getHost() ); + this.setPort( url.getPort() ); + this.setPath( url.getPath() ); + } + + + public String getProtocol( ){ + return protocol; + } + public String getHost( ){ + return host; + } + public int getPort( ){ + return port; + } + public String getPath( ){ + return path; + } + public String getAnchor( ){ + return anchor; + } + + public void setProtocol( String prot ){ + this.protocol = prot; + } + public void setHost( String host ){ + this.host = host; + } + public void setPort( int port ){ + this.port = port; + } + public void setPath( String path ){ + if( path.length() >= 1 && !path.startsWith(PATH_SEPARATOR)) + path = PATH_SEPARATOR + path; + this.path = path; + } + public void setAnchor( String anch ){ + this.anchor = anch; + } + public void setParameter( String key, String value ){ + this.parameters.put(key, value); + } + + protected void setParameters( HashMap pars ){ + this.parameters = pars; + } + + /** + * Generates the parameter string in a URL. + * + * e.g. + * "key=value&key2=value&..." + */ + public String getParameterString(){ + StringBuilder param = new StringBuilder(); + for(String key : parameters.keySet()){ + param.append(key); + param.append('='); + param.append( parameters.get(key) ); + param.append('&'); + } + if( param.length() > 0 ) + param.deleteCharAt( param.length()-1 ); + return param.toString(); + } + + /** + * Generates a path that are used in the HTTP header + */ + public String getHttpURL(){ + StringBuilder url = new StringBuilder(); + url.append( path ); + if( !parameters.isEmpty() ) + url.append( PARAMETER_SEPARATOR ).append( getParameterString() ); + + return url.toString(); + } + + /** + * Generates a full URL + */ + public String getURL(){ + return toString(); + } + + /** + * Generates the whole URL + */ + public String toString(){ + StringBuilder url = new StringBuilder(); + url.append( protocol ); + url.append( PROTOCOL_SEPARATOR ); + url.append( host ); + if( port > 0 ) + url.append( PORT_SEPARATOR ).append( port ); + + if( path != null ) + url.append( path ); + else + url.append( PATH_SEPARATOR ); + + if( !parameters.isEmpty() ) + url.append( PARAMETER_SEPARATOR ).append( getParameterString() ); + if( anchor != null ) + url.append( ANCHOR_SEPARATOR ).append( anchor ); + + return url.toString(); + } +} diff --git a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/DeviceTrait.java b/src/zutil/net/http/multipart/MultipartField.java similarity index 59% rename from plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/DeviceTrait.java rename to src/zutil/net/http/multipart/MultipartField.java index 8a2dbec2..00c73029 100644 --- a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/DeviceTrait.java +++ b/src/zutil/net/http/multipart/MultipartField.java @@ -1,49 +1,70 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.assistant.google.trait; - -import com.google.actions.api.smarthome.ExecuteRequest; -import se.hal.intf.HalAbstractDevice; -import se.hal.intf.HalDeviceConfig; -import se.hal.intf.HalDeviceData; - -import java.util.HashMap; - -/** - * https://developers.google.com/assistant/smarthome/traits - */ -public abstract class DeviceTrait { - - /** - * @return the API specific ID of this trait - */ - abstract String getId(); - - public abstract HashMap generateSyncResponse(HalDeviceConfig config); - - public abstract HashMap generateQueryResponse(HalDeviceData data); - - public void execute(HalAbstractDevice device, ExecuteRequest.Inputs.Payload.Commands.Execution execution) {} -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http.multipart; + + +/** + * A class for handling multipart field + * + * @author Ziver + */ +public class MultipartField{ + protected long received; + protected long length; + protected String contentType; + + protected String fieldname; + protected String value; + + + protected MultipartField(){ + + } + + /** + * @return the amount of data received for this field + */ + public long getReceivedBytes(){ + return received; + } + + /** + * @return the fieldname + */ + public String getFieldname(){ + return fieldname; + } + + /** + * @return the value of the field + */ + public String getValue(){ + return value; + } + + protected void parse(){ + + } +} diff --git a/src/zutil/net/http/multipart/MultipartFile.java b/src/zutil/net/http/multipart/MultipartFile.java new file mode 100644 index 00000000..a9f9bcf5 --- /dev/null +++ b/src/zutil/net/http/multipart/MultipartFile.java @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http.multipart; + +import java.io.File; + + +/** + * A class for handling multipart files + * + * @author Ziver + */ +public class MultipartFile extends MultipartField{ + protected String filename; + protected File file; + + + protected MultipartFile(File tempFile){ + this.file = tempFile; + } + + /** + * @return the amount of data received for this field + */ + public long getReceivedBytes(){ + return received; + } + + /** + * @return the value of the field + */ + public String getValue(){ + return null; + } + + /** + * @return the filename + */ + public String getFilename(){ + return filename; + } + + /** + * @return the File class that points to the received file + */ + public File getFile(){ + return file; + } + + /** + * Moves this file + * + * @param new_file is the new location to move the file to + * @return if the move was successful + */ + public boolean moveFile(File new_file){ + boolean success = file.renameTo(new_file); + if(success) + file = new_file; + return success; + } +} diff --git a/src/zutil/net/http/multipart/MultipartParser.java b/src/zutil/net/http/multipart/MultipartParser.java new file mode 100755 index 00000000..caabd74f --- /dev/null +++ b/src/zutil/net/http/multipart/MultipartParser.java @@ -0,0 +1,145 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http.multipart; + +import zutil.ProgressListener; +import zutil.net.http.HttpHeader; + +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Parses a multipart/form-data http request, + * saves files to temporary location. + * + * http://www.ietf.org/rfc/rfc1867.txt + * + * @author Ziver + * + */ +public class MultipartParser { + /** This is the temporary directory for the received files */ + private File tempDir; + /** This is the delimiter that will separate the fields */ + private String delimiter; + /** The length of the HTTP Body */ + private long contentLength; + /** This is the input stream */ + private BufferedReader in; + + /** This is the listener that will listen on the progress */ + private ProgressListener listener; + + + + public MultipartParser(BufferedReader in, HttpHeader header){ + this.in = in; + + String cotype = header.getHeader("Content-type"); + cotype = cotype.split(" *; *")[1]; + delimiter = cotype.split(" *= *")[1]; + + contentLength = Long.parseLong( header.getHeader("Content-Length") ); + } + + public MultipartParser(BufferedReader in, HttpServletRequest req){ + this.in = in; + + String cotype = req.getHeader("Content-type"); + cotype = cotype.split(" *; *")[1]; + delimiter = cotype.split(" *= *")[1]; + + contentLength = req.getContentLength(); + } + + public MultipartParser(BufferedReader in, String delimiter, long length){ + this.in = in; + this.delimiter = delimiter; + this.contentLength = length; + } + + + /** + * @param listener is the listener that will be called for progress + */ + public void setListener(ProgressListener listener){ + this.listener = listener; + } + + /** + * Parses the HTTP Body and returns a list of fields + * + * @return A list of FormField + */ + public List parse() throws IOException{ + ArrayList list = new ArrayList(); + parse(list, delimiter); + return list; + } + + + private void parse(List list, String delimiter) throws IOException{ + // TODO: + } + + + /** + * Creates a temporary file in either the system + * temporary folder or by the setTempDir() function + * + * @return the temporary file + */ + protected File createTempFile() throws IOException{ + if(tempDir != null) + return File.createTempFile("upload", ".part", tempDir.getAbsoluteFile()); + else + return File.createTempFile("upload", ".part"); + } + + /** + * Sets the initial delimiter + * + * @param delimiter is the new delimiter + */ + public void setDelimiter(String delimiter){ + this.delimiter = delimiter; + } + + public void setTempDir(File dir){ + if(!dir.isDirectory()) + throw new RuntimeException("\""+dir.getAbsolutePath()+"\" is not a directory!"); + if(!dir.canWrite()) + throw new RuntimeException("\""+dir.getAbsolutePath()+"\" is not writable!"); + tempDir = dir; + } + + public long getContentLength(){ + return contentLength; + } +} diff --git a/src/zutil/net/http/page/HttpFilePage.java b/src/zutil/net/http/page/HttpFilePage.java new file mode 100755 index 00000000..d098e0d5 --- /dev/null +++ b/src/zutil/net/http/page/HttpFilePage.java @@ -0,0 +1,164 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http.page; + +import zutil.io.IOUtil; +import zutil.io.file.FileUtil; +import zutil.log.LogUtil; +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpPage; +import zutil.net.http.HttpPrintStream; + +import java.io.*; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This Http Page will host static content from the server. + * + * Created by Ziver on 2015-03-30. + */ +public class HttpFilePage implements HttpPage{ + private static final Logger log = LogUtil.getLogger(); + + private File resource_root; + private boolean showFolders; + private boolean redirectToIndex; + + /** + * @param file a reference to a root directory or a file. + */ + public HttpFilePage(File file){ + this.resource_root = file; + this.showFolders = true; + this.redirectToIndex = true; + } + + + @Override + public void respond(HttpPrintStream out, + HttpHeader headers, + Map session, + Map cookie, + Map request) throws IOException{ + + try { + // Is the root only one file or a folder + if (resource_root.isFile()) { + deliverFile(resource_root, out); + } + else { // Resource root is a folder + File file = new File(resource_root, + headers.getRequestURL()); + if(file.getCanonicalPath().startsWith(resource_root.getCanonicalPath())){ + if(file.isDirectory() && showFolders){ + File indexFile = new File(file, "index.html"); + // Redirect to index.html + if(redirectToIndex && indexFile.isFile()) { + deliverFile(indexFile, out); + } + // Show folder contents + else if(showFolders){ + out.println("

    Directory: " + headers.getRequestURL() + "

    "); + out.println("
      "); + for (String f : file.list()) { + String url = headers.getRequestURL(); + out.println("
    • " + f + "
    • "); + } + out.println("

    "); + } + else { + throw new SecurityException("User not allowed to view folder: root=" + resource_root.getAbsolutePath()); + } + } + else { + deliverFile(file, out); + } + } + else { + throw new SecurityException("File is outside of root directory: root=" + resource_root.getAbsolutePath() + " file=" + file.getAbsolutePath()); + } + } + + }catch (FileNotFoundException e){ + if(!out.isHeaderSent()) + out.setStatusCode(404); + log.log(Level.WARNING, e.getMessage()); + out.println("404 Page Not Found: " + headers.getRequestURL()); + }catch (SecurityException e){ + if(!out.isHeaderSent()) + out.setStatusCode(404); + log.log(Level.WARNING, e.getMessage()); + out.println("404 Page Not Found: " + headers.getRequestURL() ); + }catch (IOException e){ + if(!out.isHeaderSent()) + out.setStatusCode(500); + log.log(Level.WARNING, null, e); + out.println("500 Internal Server Error: "+e.getMessage() ); + } + } + + private void deliverFile(File file, HttpPrintStream out) throws IOException { + out.setHeader("Content-Type", getMIMEType(file)); + out.flush(); + + //InputStream in = new BufferedInputStream(new FileInputStream(file)); + InputStream in = new FileInputStream(file); + IOUtil.copyStream(in, out); + in.close(); + } + + private String getMIMEType(File file){ + switch(FileUtil.getFileExtension(file)){ + case "css": return "text/css"; + case "cvs": return "text/csv"; + case "jpg": return "image/jpeg"; + case "js": return "application/javascript"; + case "png": return "image/png"; + case "htm": + case "html": return "text/html"; + case "xml": return "text/xml"; + default: return "text/plain"; + } + } + + + /** + * Enable or disable showing of folder contents + */ + public void showFolders(boolean enabled){ + this.showFolders = enabled; + } + + /** + * If directory links should be redirected to index files + */ + public void redirectToIndexFile(boolean enabled){ + this.redirectToIndex = enabled; + } +} diff --git a/src/zutil/net/nio/NioClient.java b/src/zutil/net/nio/NioClient.java new file mode 100644 index 00000000..6ad6bf86 --- /dev/null +++ b/src/zutil/net/nio/NioClient.java @@ -0,0 +1,81 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio; + +import zutil.net.nio.message.Message; +import zutil.net.nio.message.type.ResponseRequestMessage; +import zutil.net.nio.response.ResponseEvent; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; + + +public class NioClient extends NioNetwork{ + private SocketChannel serverSocket; + + /** + * Creates a NioClient that connects to a server + * + * @param hostAddress The server address + * @param port The port to listen on + */ + public NioClient(InetAddress serverAddress, int port) throws IOException { + super(InetAddress.getLocalHost(), port, NetworkType.CLIENT); + serverSocket = initiateConnection(new InetSocketAddress(serverAddress, port)); + Thread thread = new Thread(this); + thread.setDaemon(false); + thread.start(); + } + + protected Selector initSelector() throws IOException { + // Create a new selector + return SelectorProvider.provider().openSelector(); + } + + /** + * Sends a Message to the default server + * + * @param data The data to be sent + * @throws IOException Something got wrong + */ + public void send(Message data) throws IOException { + send(serverSocket, data); + } + + /** + * This method is for the Client to send a message to the server + * + * @param handler The response handler + * @param data The data to send + * @throws IOException + */ + public void send(ResponseEvent handler, ResponseRequestMessage data) throws IOException { + send(serverSocket, handler, data); + } +} diff --git a/src/zutil/net/nio/NioNetwork.java b/src/zutil/net/nio/NioNetwork.java new file mode 100755 index 00000000..5e36f080 --- /dev/null +++ b/src/zutil/net/nio/NioNetwork.java @@ -0,0 +1,471 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio; + +import zutil.Encrypter; +import zutil.converter.Converter; +import zutil.io.DynamicByteArrayStream; +import zutil.io.MultiPrintStream; +import zutil.log.LogUtil; +import zutil.net.nio.message.type.ResponseRequestMessage; +import zutil.net.nio.message.type.SystemMessage; +import zutil.net.nio.response.ResponseEvent; +import zutil.net.nio.server.ChangeRequest; +import zutil.net.nio.server.ClientData; +import zutil.net.nio.worker.SystemWorker; +import zutil.net.nio.worker.Worker; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.*; +import java.util.logging.Logger; + + +public abstract class NioNetwork implements Runnable { + private static Logger logger = LogUtil.getLogger(); + public static enum NetworkType {SERVER, CLIENT}; + + private NetworkType type; + + // The host:port combination to listen on + protected InetAddress address; + protected int port; + + // The channel on which we'll accept connections + protected ServerSocketChannel serverChannel; + // The selector we'll be monitoring + private Selector selector; + // The buffer into which we'll read data when it's available + private ByteBuffer readBuffer = ByteBuffer.allocate(8192); + protected Worker worker; + protected SystemWorker systemWorker; + + // This map contains all the clients that are conncted + protected Map clients = new HashMap(); + + // A list of PendingChange instances + private List pendingChanges = new LinkedList(); + // Maps a SocketChannel to a list of ByteBuffer instances + private Map> pendingWriteData = new HashMap>(); + private Map pendingReadData = new HashMap(); + // The encrypter + private Encrypter encrypter; + + /** + * Create a nio network class + * + * @param hostAddress The host address + * @param port The port + * @param type The type of network host + * @throws IOException + */ + public NioNetwork(InetAddress address, int port, NetworkType type) throws IOException { + this.port = port; + this.address = address; + this.type = type; + this.selector = initSelector(); + this.systemWorker = new SystemWorker(this); + } + + protected abstract Selector initSelector() throws IOException; + + /** + * Sets the Worker for the network messages + * + * @param worker The worker that handles the incoming messages + */ + public void setDefaultWorker(Worker worker){ + this.worker = worker; + } + + /** + * Sets the encrypter to use in the network + * + * @param enc The encrypter to use or null fo no encryption + */ + public void setEncrypter(Encrypter enc){ + encrypter = enc; + MultiPrintStream.out.println("Network Encryption "+ + (encrypter != null ? "Enabled("+encrypter.getAlgorithm()+")" : "Disabled")+"!!"); + } + + public void send(SocketChannel socket, Object data) throws IOException{ + send(socket, Converter.toBytes(data)); + } + + public void send(InetSocketAddress address, Object data) throws IOException{ + send(address, Converter.toBytes(data)); + } + + public void send(InetSocketAddress address, byte[] data){ + send(getSocketChannel(address), data); + } + + public void send(SocketChannel socket, ResponseEvent handler, ResponseRequestMessage data) throws IOException { + // Register the response handler + systemWorker.addResponseHandler(handler, data); + + queueSend(socket,Converter.toBytes(data)); + } + + /** + * This method sends data true the given socket + * + * @param socket The socket + * @param data The data to send + */ + public void send(SocketChannel socket, byte[] data) { + queueSend(socket,data); + } + + /** + * Queues the message to be sent and wakeups the selector + * + * @param socket The socet to send the message thrue + * @param data The data to send + */ + protected void queueSend(SocketChannel socket, byte[] data){ + logger.finest("Sending Queue..."); + // And queue the data we want written + synchronized (pendingWriteData) { + List queue = pendingWriteData.get(socket); + if (queue == null) { + queue = new ArrayList(); + pendingWriteData.put(socket, queue); + } + //encrypts + if(encrypter != null) + queue.add(ByteBuffer.wrap(encrypter.encrypt(data))); + else queue.add(ByteBuffer.wrap(data)); + } + // Changing the key state to write + synchronized (pendingChanges) { + // Indicate we want the interest ops set changed + pendingChanges.add(new ChangeRequest(socket, ChangeRequest.CHANGEOPS, SelectionKey.OP_WRITE)); + } + logger.finest("selector.wakeup();"); + // Finally, wake up our selecting thread so it can make the required changes + selector.wakeup(); + } + + public void run() { + logger.fine("NioNetwork Started!!!"); + while (true) { + try { + // Process any pending changes + synchronized (pendingChanges) { + Iterator changes = pendingChanges.iterator(); + while (changes.hasNext()) { + ChangeRequest change = changes.next(); + switch (change.type) { + case ChangeRequest.CHANGEOPS: + SelectionKey key = change.socket.keyFor(selector); + key.interestOps(change.ops); + logger.finest("change.ops "+change.ops); + break; + case ChangeRequest.REGISTER: + change.socket.register(selector, change.ops); + logger.finest("register socket "); + break; + } + } + pendingChanges.clear(); + } + + // Wait for an event one of the registered channels + selector.select(); + logger.finest("selector is awake"); + + // Iterate over the set of keys for which events are available + Iterator selectedKeys = selector.selectedKeys().iterator(); + while (selectedKeys.hasNext()) { + SelectionKey key = (SelectionKey) selectedKeys.next(); + selectedKeys.remove(); + logger.finest("KeyOP: "+key.interestOps()+" isAcceptable: "+SelectionKey.OP_ACCEPT+" isConnectable: "+SelectionKey.OP_CONNECT+" isWritable: "+SelectionKey.OP_WRITE+" isReadable: "+SelectionKey.OP_READ); + + if (key.isValid()) { + // Check what event is available and deal with it + if (key.isAcceptable()) { + logger.finest("Accepting Connection!!"); + accept(key); + } + else if (key.isConnectable()) { + logger.finest("Finnishing Connection!!"); + finishConnection(key); + } + else if (key.isWritable()) { + logger.finest("Writing"); + write(key); + } + else if (key.isReadable()) { + logger.finest("Reading"); + read(key); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * Server + */ + private void accept(SelectionKey key) throws IOException { + // For an accept to be pending the channel must be a server socket channel. + ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); + + // Accept the connection and make it non-blocking + SocketChannel socketChannel = serverSocketChannel.accept(); + socketChannel.socket().setReuseAddress(true); + socketChannel.configureBlocking(false); + + // Register the new SocketChannel with our Selector, indicating + // we'd like to be notified when there's data waiting to be read + socketChannel.register(selector, SelectionKey.OP_READ); + + // adds the client to the clients list + InetSocketAddress remoteAdr = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); + if(!clients.containsValue(remoteAdr)){ + clients.put(remoteAdr, new ClientData(socketChannel)); + logger.fine("New Connection("+remoteAdr+")!!! Count: "+clients.size()); + } + } + + /** + * Client and Server + */ + private void read(SelectionKey key) throws IOException { + SocketChannel socketChannel = (SocketChannel) key.channel(); + InetSocketAddress remoteAdr = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); + + // Clear out our read buffer so it's ready for new data + readBuffer.clear(); + + // Attempt to read off the channel + int numRead; + try { + numRead = socketChannel.read(readBuffer); + } catch (IOException e) { + // The remote forcibly closed the connection, cancel + // the selection key and close the channel. + key.cancel(); + socketChannel.close(); + clients.remove(remoteAdr); + pendingReadData.remove(socketChannel); + pendingWriteData.remove(socketChannel); + logger.fine("Connection Forced Close("+remoteAdr+")!!! Connection Count: "+clients.size()); + if(type == NetworkType.CLIENT) + throw new IOException("Server Closed The Connection!!!"); + return; + } + + if (numRead == -1) { + // Remote entity shut the socket down cleanly. Do the + // same from our end and cancel the channel. + key.channel().close(); + key.cancel(); + clients.remove(remoteAdr); + pendingReadData.remove(socketChannel); + pendingWriteData.remove(socketChannel); + logger.fine("Connection Close("+remoteAdr+")!!! Connection Count: "+clients.size()); + if(type == NetworkType.CLIENT) + throw new IOException("Server Closed The Connection!!!"); + return; + } + + // Make a correctly sized copy of the data before handing it + // to the client + byte[] rspByteData = new byte[numRead]; + System.arraycopy(readBuffer.array(), 0, rspByteData, 0, numRead); + if(encrypter != null)// Encryption + rspByteData = encrypter.decrypt(rspByteData); + + // Message Count 1m: 36750 + // Message Count 1s: 612 + if(!pendingReadData.containsKey(socketChannel)){ + pendingReadData.put(socketChannel, new DynamicByteArrayStream()); + } + DynamicByteArrayStream dynBuf = pendingReadData.get(socketChannel); + dynBuf.append(rspByteData); + + + Object rspData = null; + try{ + //rspData = Converter.toObject(rspByteData); + rspData = Converter.toObject(dynBuf); + handleRecivedMessage(socketChannel, rspData); + dynBuf.clear(); + }catch(Exception e){ + e.printStackTrace(); + dynBuf.reset(); + } + } + + /** + * Client and Server + */ + private void write(SelectionKey key) throws IOException { + SocketChannel socketChannel = (SocketChannel) key.channel(); + + synchronized (pendingWriteData) { + List queue = pendingWriteData.get(socketChannel); + if(queue == null){ + queue = new ArrayList(); + pendingWriteData.put(socketChannel, queue); + } + + // Write until there's not more data ... + while (!queue.isEmpty()) { + ByteBuffer buf = queue.get(0); + socketChannel.write(buf); + if (buf.remaining() > 0) { + // ... or the socket's buffer fills up + logger.finest("Write Buffer Full!!"); + break; + } + queue.remove(0); + } + + if (queue.isEmpty()) { + // We wrote away all data, so we're no longer interested + // in writing on this socket. Switch back to waiting for + // data. + logger.finest("No more Data to write!!"); + key.interestOps(SelectionKey.OP_READ); + } + } + } + + private void handleRecivedMessage(SocketChannel socketChannel, Object rspData){ + logger.finer("Handling incomming message..."); + + if(rspData instanceof SystemMessage){ + if(systemWorker != null){ + logger.finest("System Message!!!"); + systemWorker.processData(this, socketChannel, rspData); + } + else{ + logger.finer("Unhandled System Message!!!"); + } + } + else{ + // Hand the data off to our worker thread + if(worker != null){ + logger.finest("Worker Message!!!"); + worker.processData(this, socketChannel, rspData); + } + else{ + logger.fine("Unhandled Worker Message!!!"); + } + } + } + + /** + * Initializes a socket to a server + */ + protected SocketChannel initiateConnection(InetSocketAddress address) throws IOException { + // Create a non-blocking socket channel + SocketChannel socketChannel = SocketChannel.open(); + socketChannel.socket().setReuseAddress(true); + socketChannel.configureBlocking(false); + logger.fine("Connecting to: "+address); + + // Kick off connection establishment + socketChannel.connect(address); + + // Queue a channel registration since the caller is not the + // selecting thread. As part of the registration we'll register + // an interest in connection events. These are raised when a channel + // is ready to complete connection establishment. + synchronized(this.pendingChanges) { + pendingChanges.add(new ChangeRequest(socketChannel, ChangeRequest.REGISTER, SelectionKey.OP_CONNECT)); + } + + return socketChannel; + } + + protected SocketChannel getSocketChannel(InetSocketAddress address){ + return clients.get(address).getSocketChannel(); + } + + /** + * Client + */ + private void finishConnection(SelectionKey key){ + SocketChannel socketChannel = (SocketChannel) key.channel(); + + // Finish the connection. If the connection operation failed + // this will raise an IOException. + try { + socketChannel.finishConnect(); + } catch (IOException e) { + // Cancel the channel's registration with our selector + e.printStackTrace(); + key.cancel(); + return; + } + + // Register an interest in writing on this channel + key.interestOps(SelectionKey.OP_WRITE); + } + + /** + * Client + * @throws IOException + */ + protected void closeConnection(SocketChannel socketChannel) throws IOException{ + socketChannel.close(); + socketChannel.keyFor(selector).cancel(); + } + + /** + * Client + * @throws IOException + */ + protected void closeConnection(InetSocketAddress address) throws IOException{ + closeConnection(getSocketChannel(address)); + } + + /* + public void close() throws IOException{ + if(serverChannel != null){ + serverChannel.close(); + serverChannel.keyFor(selector).cancel(); + } + selector.close(); + }*/ + + public NetworkType getType(){ + return type; + } +} diff --git a/src/zutil/net/nio/NioServer.java b/src/zutil/net/nio/NioServer.java new file mode 100644 index 00000000..14f11923 --- /dev/null +++ b/src/zutil/net/nio/NioServer.java @@ -0,0 +1,92 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.spi.SelectorProvider; +import java.util.Iterator; + +public class NioServer extends NioNetwork{ + + /** + * Creates a NioServer object which listens on localhost + * + * @param port The port to listen to + */ + public NioServer(int port) throws IOException { + this(null, port); + } + + /** + * Creates a NioServer object which listens to a specific address + * + * @param address The address to listen to + * @param port The port to listen to + */ + public NioServer(InetAddress address, int port) throws IOException { + super(address, port, NetworkType.SERVER); + new Thread(this).start(); + } + + protected Selector initSelector() throws IOException { + // Create a new selector + Selector socketSelector = SelectorProvider.provider().openSelector(); + + // Create a new non-blocking server socket channel + serverChannel = ServerSocketChannel.open(); + serverChannel.socket().setReuseAddress(true); + serverChannel.configureBlocking(false); + + // Bind the server socket to the specified address and port + InetSocketAddress isa = new InetSocketAddress(address, port); + serverChannel.socket().bind(isa); + + // Register the server socket channel, indicating an interest in + // accepting new connections + serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT); + + return socketSelector; + } + + /** + * Broadcasts the message to all the connected clients + * + * @param data The data to broadcast + */ + public void broadcast(byte[] data){ + synchronized(clients){ + Iterator it = clients.keySet().iterator(); + while(it.hasNext()){ + send(it.next(), data); + } + } + } + +} diff --git a/src/zutil/net/nio/message/ChatMessage.java b/src/zutil/net/nio/message/ChatMessage.java new file mode 100644 index 00000000..0d5cf0fd --- /dev/null +++ b/src/zutil/net/nio/message/ChatMessage.java @@ -0,0 +1,69 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message; + +public class ChatMessage extends Message{ + private static final long serialVersionUID = 1L; + + public static enum ChatMessageType {REGISTER, UNREGISTER, MESSAGE}; + + public ChatMessageType type; + public String msg; + public String room; + + /** + * Registers the user to the main chat + * + * @param name Name of user + */ + public ChatMessage(){ + this("", "", ChatMessageType.REGISTER); + } + + /** + * Registers the user to the given room + * + * @param room The room to register to + */ + public ChatMessage(String room){ + this("", room, ChatMessageType.REGISTER); + } + + /** + * Sends a message to the given room + * + * @param msg The message + * @param room The room + */ + public ChatMessage(String msg, String room){ + this(msg, room, ChatMessageType.MESSAGE); + } + + public ChatMessage(String msg, String room, ChatMessageType type){ + this.msg = msg; + this.room = room; + this.type = type; + } +} diff --git a/src/zutil/net/nio/message/GraphicsSyncMessage.java b/src/zutil/net/nio/message/GraphicsSyncMessage.java new file mode 100644 index 00000000..019d34f6 --- /dev/null +++ b/src/zutil/net/nio/message/GraphicsSyncMessage.java @@ -0,0 +1,55 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message; + + +public class GraphicsSyncMessage extends SyncMessage{ + private static final long serialVersionUID = 1L; + + public float locX; + public float locY; + public float locZ; + + public float rotX; + public float rotY; + public float rotZ; + public float rotW; + + public GraphicsSyncMessage(String id){ + this.type = MessageType.SYNC; + this.id = id; + } + + public boolean equals(Object obj){ + if(obj instanceof GraphicsSyncMessage){ + GraphicsSyncMessage tmp = (GraphicsSyncMessage)obj; + return (tmp.locX == locX && tmp.locY == locY && + tmp.locZ == locZ && tmp.rotX == rotX && + tmp.rotY == rotY && tmp.rotZ == rotZ && + tmp.rotW == rotW); + } + return false; + } +} diff --git a/src/zutil/net/nio/message/GridMessage.java b/src/zutil/net/nio/message/GridMessage.java new file mode 100644 index 00000000..09773fc0 --- /dev/null +++ b/src/zutil/net/nio/message/GridMessage.java @@ -0,0 +1,108 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message; + +public class GridMessage extends Message{ + private static final long serialVersionUID = 1L; + + // Client type messages + /** Computation job return right answer **/ + public static final int COMP_SUCCESSFUL = 1; // + /** Initial static data **/ + public static final int COMP_INCORRECT = 2; // + /** Computation job return wrong answer **/ + public static final int COMP_ERROR = 3; // + /** There was an error computing **/ + public static final int REGISTER = 4; // + /** Register at the server **/ + public static final int UNREGISTER = 5; // + /** Request new computation data **/ + public static final int NEW_DATA = 6; // + + // Server type messages + /** Sending initial static data **/ + public static final int INIT_DATA = 100; + /** Sending new dynamic data **/ + public static final int COMP_DATA = 101; + + + private int type; + private int jobID; + private T data; + + /** + * Creates a new GridMessage + * + * @param type is the type of message + * @param jobID is the id of the job + */ + public GridMessage(int type){ + this(type, 0, null); + } + + /** + * Creates a new GridMessage + * + * @param type is the type of message + * @param jobID is the id of the job + */ + public GridMessage(int type, int jobID){ + this(type, jobID, null); + } + + /** + * Creates a new GridMessage + * + * @param type is the type of message + * @param jobID is the id of the job + * @param data is the data to send with this message + */ + public GridMessage(int type, int jobID, T data){ + this.type = type; + this.jobID = jobID; + this.data = data; + } + + /** + * @return the type of message + */ + public int messageType(){ + return type; + } + + /** + * @return the job id for this message + */ + public int getJobQueueID(){ + return jobID; + } + + /** + * @return the data in this message, may not always carry any data. + */ + public T getData(){ + return data; + } +} diff --git a/src/zutil/net/nio/message/KeepAliveMessage.java b/src/zutil/net/nio/message/KeepAliveMessage.java new file mode 100644 index 00000000..c265c068 --- /dev/null +++ b/src/zutil/net/nio/message/KeepAliveMessage.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message; + +import zutil.net.nio.message.type.SystemMessage; + +/** + * Tells the destination that the + * source is still online + * + * @author Ziver + * + */ +public class KeepAliveMessage extends Message implements SystemMessage{ + + private static final long serialVersionUID = 1L; + +} diff --git a/plugins/hal-dummy/src/se/hal/plugin/dummy/DummyDevice.java b/src/zutil/net/nio/message/Message.java similarity index 83% rename from plugins/hal-dummy/src/se/hal/plugin/dummy/DummyDevice.java rename to src/zutil/net/nio/message/Message.java index cb09e504..6785e129 100644 --- a/plugins/hal-dummy/src/se/hal/plugin/dummy/DummyDevice.java +++ b/src/zutil/net/nio/message/Message.java @@ -1,33 +1,33 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.dummy; - -import se.hal.intf.HalDeviceConfig; -import se.hal.intf.HalDeviceData; - -public interface DummyDevice extends HalDeviceConfig { - - HalDeviceData generateData(); -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message; + +import java.io.Serializable; + +public class Message implements Serializable{ + private static final long serialVersionUID = 1L; + + +} diff --git a/src/zutil/net/nio/message/StringMessage.java b/src/zutil/net/nio/message/StringMessage.java new file mode 100644 index 00000000..f0d8d7e2 --- /dev/null +++ b/src/zutil/net/nio/message/StringMessage.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message; + +import zutil.net.nio.message.type.EchoMessage; +import zutil.net.nio.message.type.ResponseRequestMessage; + + + +public class StringMessage extends EchoMessage implements ResponseRequestMessage{ + private static final long serialVersionUID = 1L; + private double responseId; + + private String msg; + + public StringMessage(String msg){ + this.msg = msg; + responseId = Math.random(); + } + + public String getString(){ + return msg; + } + + public void setString(String msg){ + this.msg = msg; + } + + public String toString(){ + return getString(); + } + + public double getResponseId() { + return responseId; + } +} diff --git a/src/zutil/net/nio/message/SyncMessage.java b/src/zutil/net/nio/message/SyncMessage.java new file mode 100644 index 00000000..950ae785 --- /dev/null +++ b/src/zutil/net/nio/message/SyncMessage.java @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message; + +import zutil.net.nio.message.type.SystemMessage; + +public class SyncMessage extends Message implements SystemMessage{ + private static final long serialVersionUID = 1L; + public static enum MessageType { REQUEST_ID, NEW, REMOVE, SYNC }; + + // type of message + public MessageType type; + // id of the Object + public String id; +} diff --git a/src/zutil/net/nio/message/type/EchoMessage.java b/src/zutil/net/nio/message/type/EchoMessage.java new file mode 100644 index 00000000..6fcc22c9 --- /dev/null +++ b/src/zutil/net/nio/message/type/EchoMessage.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message.type; + +import zutil.net.nio.message.Message; + +/** + * The reciver will echo out this message to the sender + * + * @author Ziver + */ +public abstract class EchoMessage extends Message implements SystemMessage{ + private static final long serialVersionUID = 1L; + + private boolean echo; + + public EchoMessage(){ + echo = true; + } + + /** + * This method returns if the message should be echoed + * @return If the message should be echoed + */ + public boolean echo() { + return echo; + } + + /** + * Called by the reciver to disable looping of the message + * + */ + public void recived() { + echo = false; + } +} diff --git a/src/zutil/net/nio/message/type/ResponseRequestMessage.java b/src/zutil/net/nio/message/type/ResponseRequestMessage.java new file mode 100644 index 00000000..7429215f --- /dev/null +++ b/src/zutil/net/nio/message/type/ResponseRequestMessage.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message.type; + +/** + * This interface means that the sender + * wants a reply from the destination + * + * @author Ziver + * + */ +public interface ResponseRequestMessage { + + /** + * The id of the response to identify the response event + * @return Response id + */ + public double getResponseId(); + +} diff --git a/src/zutil/net/nio/message/type/SystemMessage.java b/src/zutil/net/nio/message/type/SystemMessage.java new file mode 100644 index 00000000..5fc5508b --- /dev/null +++ b/src/zutil/net/nio/message/type/SystemMessage.java @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.message.type; + +/** + * A message that implements this will be + * handeld internaly by the network engine + * + * @author Ziver + * + */ +public interface SystemMessage { + +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraData.java b/src/zutil/net/nio/response/PrintRsp.java similarity index 80% rename from plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraData.java rename to src/zutil/net/nio/response/PrintRsp.java index 5cf0141e..32bcac60 100644 --- a/plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraData.java +++ b/src/zutil/net/nio/response/PrintRsp.java @@ -1,40 +1,36 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.nvr.intf; - -import se.hal.intf.HalDeviceData; - -public class HalCameraData extends HalDeviceData { - - @Override - public double getData() { - return 0; - } - - @Override - public void setData(double data) { - - } -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.response; + +import zutil.io.MultiPrintStream; + +public class PrintRsp extends ResponseEvent{ + + @Override + protected void responseEvent(Object rsp) { + MultiPrintStream.out.println(rsp); + } + +} diff --git a/src/zutil/net/nio/response/ResponseEvent.java b/src/zutil/net/nio/response/ResponseEvent.java new file mode 100644 index 00000000..21d660e8 --- /dev/null +++ b/src/zutil/net/nio/response/ResponseEvent.java @@ -0,0 +1,67 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.response; + + +public abstract class ResponseEvent { + private Object rsp = null; + + public synchronized boolean handleResponse(Object rsp) { + this.rsp = rsp; + notify(); + return true; + } + + /** + * Blocks the Thread until there is a response + */ + public synchronized void waitForResponse() { + while(!gotResponse()) { + try { + this.wait(); + } catch (InterruptedException e) {} + } + + responseEvent(rsp); + } + + /** + * Handles the response + */ + public void handleResponse(){ + if(gotResponse()){ + responseEvent(rsp); + } + } + + /** + * @return If there is an response + */ + public boolean gotResponse(){ + return (rsp != null); + } + + protected abstract void responseEvent(Object rsp); +} diff --git a/src/zutil/net/nio/response/ResponseHandler.java b/src/zutil/net/nio/response/ResponseHandler.java new file mode 100644 index 00000000..3cd19682 --- /dev/null +++ b/src/zutil/net/nio/response/ResponseHandler.java @@ -0,0 +1,65 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.response; + +import java.util.LinkedList; +import java.util.List; + + +public abstract class ResponseHandler implements Runnable{ + private List queue = new LinkedList(); + + public ResponseHandler(){ + + } + + public synchronized void addResponseEvent(ResponseEvent re){ + queue.add(re); + notify(); + } + + public synchronized void removeResponseEvent(ResponseEvent re){ + queue.remove(re); + } + + public void run() { + while(true) { + try { + this.wait(); + } catch (InterruptedException e) {} + + update(); + } + } + + public synchronized void update(){ + while(!queue.isEmpty()){ + queue.get(0).handleResponse(); + if(queue.get(0).gotResponse()){ + queue.remove(0); + } + } + } +} diff --git a/src/zutil/net/nio/server/ChangeRequest.java b/src/zutil/net/nio/server/ChangeRequest.java new file mode 100644 index 00000000..a752b93e --- /dev/null +++ b/src/zutil/net/nio/server/ChangeRequest.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.server; + +import java.nio.channels.SocketChannel; + +public class ChangeRequest { + public static final int REGISTER = 1; + public static final int CHANGEOPS = 2; + + public SocketChannel socket; + public int type; + public int ops; + + public ChangeRequest(SocketChannel socket, int type, int ops) { + this.socket = socket; + this.type = type; + this.ops = ops; + } +} diff --git a/src/zutil/net/nio/server/ClientData.java b/src/zutil/net/nio/server/ClientData.java new file mode 100644 index 00000000..9fc4b13f --- /dev/null +++ b/src/zutil/net/nio/server/ClientData.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.server; + +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; + +public class ClientData { + private SocketChannel socketChannel; + private long lastMessageReceived; + + public ClientData(SocketChannel socketChannel){ + this.socketChannel = socketChannel; + } + + public SocketChannel getSocketChannel(){ + return socketChannel; + } + + public InetSocketAddress getAddress(){ + return (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); + } + + public void setLastMessageReceived(long time){ + lastMessageReceived = time; + } + + public long getLastMessageReceived(){ + return lastMessageReceived; + } +} diff --git a/src/zutil/net/nio/service/NetworkService.java b/src/zutil/net/nio/service/NetworkService.java new file mode 100644 index 00000000..f06fa1ea --- /dev/null +++ b/src/zutil/net/nio/service/NetworkService.java @@ -0,0 +1,49 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.service; + +import zutil.net.nio.NioNetwork; +import zutil.net.nio.message.Message; + +import java.nio.channels.SocketChannel; + +public abstract class NetworkService { + protected static NetworkService instance; + protected NioNetwork nio; + + public NetworkService(NioNetwork nio){ + instance = this; + this.nio = nio; + } + + public abstract void handleMessage(Message message, SocketChannel socket); + + /** + * @return A instance of this class + */ + public static NetworkService getInstance(){ + return instance; + } +} diff --git a/src/zutil/net/nio/service/chat/ChatListener.java b/src/zutil/net/nio/service/chat/ChatListener.java new file mode 100644 index 00000000..2c6cd09f --- /dev/null +++ b/src/zutil/net/nio/service/chat/ChatListener.java @@ -0,0 +1,34 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.service.chat; + +/** + * Tis is a listener class for new chat messages + * @author Ziver + * + */ +public interface ChatListener { + public void messageAction(String msg, String room); +} diff --git a/src/zutil/net/nio/service/chat/ChatService.java b/src/zutil/net/nio/service/chat/ChatService.java new file mode 100644 index 00000000..55f7e1c6 --- /dev/null +++ b/src/zutil/net/nio/service/chat/ChatService.java @@ -0,0 +1,157 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.service.chat; + +import zutil.log.LogUtil; +import zutil.net.nio.NioNetwork; +import zutil.net.nio.message.ChatMessage; +import zutil.net.nio.message.Message; +import zutil.net.nio.service.NetworkService; + +import java.nio.channels.SocketChannel; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.logging.Logger; + +/** + * A simple chat service with users and rooms + * + * @author Ziver + */ +public class ChatService extends NetworkService{ + private static Logger logger = LogUtil.getLogger(); + private HashMap> rooms; + private ChatListener listener; + + public ChatService(NioNetwork nio){ + super(nio); + rooms = new HashMap>(); + } + + @Override + public void handleMessage(Message message, SocketChannel socket) { + try { + // New message + if(message instanceof ChatMessage){ + ChatMessage chatmessage = (ChatMessage)message; + //is this a new message + if(chatmessage.type == ChatMessage.ChatMessageType.MESSAGE){ + // Is this the server + if(nio.getType() == NioNetwork.NetworkType.SERVER){ + if(rooms.containsKey(chatmessage.room)){ + LinkedList tmpList = rooms.get(chatmessage.room); + + // Broadcast the message + for(SocketChannel s : tmpList){ + if(s.isConnected()){ + nio.send(s, chatmessage); + } + else{ + unRegisterUser(chatmessage.room, s); + } + } + } + } + logger.finer("New Chat Message: "+chatmessage.msg); + listener.messageAction(chatmessage.msg, chatmessage.room); + } + // register to a room + else if(chatmessage.type == ChatMessage.ChatMessageType.REGISTER){ + registerUser(chatmessage.room, socket); + } + // unregister to a room + else if(chatmessage.type == ChatMessage.ChatMessageType.UNREGISTER){ + unRegisterUser(chatmessage.room, socket); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + * Registers a user to the main room + * + * @param socket The socket to the user + */ + public void registerUser(SocketChannel socket){ + registerUser("", socket); + } + + /** + * Registers the given user to a specific room + * + * @param room The room + * @param socket The socket to the user + */ + public void registerUser(String room, SocketChannel socket){ + addRoom(room); + logger.fine("New Chat User: "+socket); + rooms.get(room).add(socket); + } + + /** + * Unregisters a user from a room and removes the room if its empty + * + * @param room The room + * @param socket The socket to the user + */ + public void unRegisterUser(String room, SocketChannel socket){ + if(rooms.containsKey(room)){ + logger.fine("Remove Chat User: "+socket); + rooms.get(room).remove(socket); + removeRoom(room); + } + } + + /** + * Adds a room into the list + * + * @param room The name of the room + */ + public void addRoom(String room){ + if(!rooms.containsKey(room)){ + logger.fine("New Chat Room: "+room); + rooms.put(room, new LinkedList()); + } + } + + /** + * Removes the given room if its empty + * + * @param room The room + */ + public void removeRoom(String room){ + if(rooms.get(room).isEmpty()){ + logger.fine("Remove Chat Room: "+room); + rooms.remove(room); + } + } + + public static ChatService getInstance(){ + return (ChatService)instance; + } +} diff --git a/src/zutil/net/nio/service/sync/ObjectSync.java b/src/zutil/net/nio/service/sync/ObjectSync.java new file mode 100644 index 00000000..5b5c2d65 --- /dev/null +++ b/src/zutil/net/nio/service/sync/ObjectSync.java @@ -0,0 +1,52 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.service.sync; + +import zutil.net.nio.message.SyncMessage; + +public abstract class ObjectSync { + public String id; + + public ObjectSync(String id){ + this.id = id; + } + + /** + * Sends sync message if the object has bean changed + */ + public abstract void sendSync(); + + /** + * Applies the SyncMessage to the object + * @param message + * @param object + */ + public abstract void syncObject(SyncMessage message); + + /** + * Called when the object is removed from the sync list + */ + public abstract void remove(); +} diff --git a/src/zutil/net/nio/service/sync/SyncService.java b/src/zutil/net/nio/service/sync/SyncService.java new file mode 100644 index 00000000..ff5eec47 --- /dev/null +++ b/src/zutil/net/nio/service/sync/SyncService.java @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.service.sync; + +import zutil.log.LogUtil; +import zutil.net.nio.NioNetwork; +import zutil.net.nio.message.Message; +import zutil.net.nio.message.SyncMessage; +import zutil.net.nio.service.NetworkService; + +import java.nio.channels.SocketChannel; +import java.util.HashMap; +import java.util.logging.Logger; + +public class SyncService extends NetworkService{ + private static Logger logger = LogUtil.getLogger(); + // list of objects to sync + private HashMap sync; + + public SyncService(NioNetwork nio){ + super(nio); + sync = new HashMap(); + } + + /** + * Adds a SyncObject to the sync list + * @param os The object to sync + */ + public void addSyncObject(ObjectSync os){ + sync.put(os.id, os); + logger.fine("New Sync object: "+os); + } + + public void handleMessage(Message message, SocketChannel socket){ + if(message instanceof SyncMessage){ + SyncMessage syncMessage = (SyncMessage)message; + if(syncMessage.type == SyncMessage.MessageType.SYNC){ + ObjectSync obj = sync.get(syncMessage.id); + if(obj != null){ + logger.finer("Syncing Message..."); + obj.syncObject(syncMessage); + } + } + else if(syncMessage.type == SyncMessage.MessageType.REMOVE){ + sync.remove(syncMessage.id).remove(); + } + } + } + + /** + * Syncs all the objects whit the server + */ + public void sync(){ + for(String id : sync.keySet()){ + sync.get(id).sendSync(); + } + } + + public static SyncService getInstance(){ + return (SyncService)instance; + } +} diff --git a/plugins/hal-vendor-ecosense/test/se/hal/plugin/vendor/ecosense/EcoSenseCloudAPIClientTest.java b/src/zutil/net/nio/worker/EchoWorker.java similarity index 68% rename from plugins/hal-vendor-ecosense/test/se/hal/plugin/vendor/ecosense/EcoSenseCloudAPIClientTest.java rename to src/zutil/net/nio/worker/EchoWorker.java index efc390ef..94dbe52a 100644 --- a/plugins/hal-vendor-ecosense/test/se/hal/plugin/vendor/ecosense/EcoSenseCloudAPIClientTest.java +++ b/src/zutil/net/nio/worker/EchoWorker.java @@ -1,43 +1,46 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2025 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.vendor.ecosense; - -import zutil.io.MultiPrintStream; - -import static org.junit.Assert.*; - -public class EcoSenseCloudAPIClientTest { - public static void main(String[] args) { - if (args.length != 2) { - System.out.println("ERROR: Please provide username and password as startup parameters."); - System.exit(1); - } - - EcoSenseCloudAPIClient client = new EcoSenseCloudAPIClient(args[0], args[1]); - client.authenticate(); - client.getDevices(); - } - -} \ No newline at end of file +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker; + +import zutil.io.MultiPrintStream; + +import java.io.IOException; + +public class EchoWorker extends ThreadedEventWorker { + + @Override + public void messageEvent(WorkerDataEvent dataEvent) { + try { + // Return to sender + MultiPrintStream.out.println("Recived Msg: "+dataEvent.data); + dataEvent.network.send(dataEvent.socket, dataEvent.data); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + +} diff --git a/src/zutil/net/nio/worker/SystemWorker.java b/src/zutil/net/nio/worker/SystemWorker.java new file mode 100644 index 00000000..43590c09 --- /dev/null +++ b/src/zutil/net/nio/worker/SystemWorker.java @@ -0,0 +1,153 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker; + +import zutil.log.LogUtil; +import zutil.net.nio.NioNetwork; +import zutil.net.nio.message.ChatMessage; +import zutil.net.nio.message.Message; +import zutil.net.nio.message.SyncMessage; +import zutil.net.nio.message.type.EchoMessage; +import zutil.net.nio.message.type.ResponseRequestMessage; +import zutil.net.nio.response.ResponseEvent; +import zutil.net.nio.service.NetworkService; +import zutil.net.nio.service.chat.ChatService; +import zutil.net.nio.service.sync.SyncService; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + + +public class SystemWorker extends ThreadedEventWorker { + private static Logger logger = LogUtil.getLogger(); + private NioNetwork nio; + // Maps a SocketChannel to a RspHandler + private Map rspEvents = new HashMap(); + // Difren services listening on specific messages + private Map, NetworkService> services = new HashMap, NetworkService>(); + /** + * Creates a new SystemWorker + * @param nio The Network + */ + public SystemWorker(NioNetwork nio){ + this.nio = nio; + } + + @Override + public void messageEvent(WorkerDataEvent event) { + try { + logger.finer("System Message: "+event.data.getClass().getName()); + if(event.data instanceof Message){ + if(event.data instanceof EchoMessage && ((EchoMessage)event.data).echo()){ + // Echos back the recived message + ((EchoMessage)event.data).recived(); + logger.finer("Echoing Message: "+event.data); + nio.send(event.socket, event.data); + } + else if(event.data instanceof ResponseRequestMessage && + rspEvents.get(((ResponseRequestMessage)event.data).getResponseId()) != null){ + // Handle the response + handleResponse(((ResponseRequestMessage)event.data).getResponseId(), event.data); + logger.finer("Response Request Message: "+event.data); + } + else{ + //Services + if(services.containsKey(event.data.getClass()) || + !services.containsKey(event.data.getClass()) && defaultServices(event.data)){ + services.get(event.data.getClass()).handleMessage((Message)event.data, event.socket); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Registers a Service to a specific message + * + * @param c The Message class + * @param ns The service + */ + public void registerService(Class c, NetworkService ns){ + services.put(c, ns); + } + + /** + * Unregisters a service + * + * @param c The class + */ + public void unregisterService(Class c){ + services.remove(c); + } + + /** + * Connects a ResponseHandler to a specific message + * @param handler The Handler + * @param data The Message + */ + public void addResponseHandler(ResponseEvent handler, ResponseRequestMessage data){ + rspEvents.put(data.getResponseId(), handler); + } + + /** + * Client And Server ResponseEvent + */ + private void handleResponse(double responseId, Object rspData){ + // Look up the handler for this channel + ResponseEvent handler = rspEvents.get(responseId); + // And pass the response to it + handler.handleResponse(rspData); + + rspEvents.remove(responseId); + } + + /** + * Registers the default services in the engin e + * if the message needs one of them + * + * @param o The message + */ + private boolean defaultServices(Object o){ + if(o instanceof SyncMessage){ + if(SyncService.getInstance() == null) + registerService(o.getClass(), new SyncService(nio)); + else + registerService(o.getClass(), SyncService.getInstance()); + return true; + } + else if(o instanceof ChatMessage){ + if(ChatService.getInstance() == null) + registerService(o.getClass(), new ChatService(nio)); + else + registerService(o.getClass(), ChatService.getInstance()); + return true; + } + return false; + } + +} diff --git a/src/zutil/net/nio/worker/ThreadedEventWorker.java b/src/zutil/net/nio/worker/ThreadedEventWorker.java new file mode 100644 index 00000000..b93f1c46 --- /dev/null +++ b/src/zutil/net/nio/worker/ThreadedEventWorker.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker; + +public abstract class ThreadedEventWorker extends Worker{ + private Thread thread; + + public ThreadedEventWorker(){ + thread = new Thread(this); + thread.start(); + } + + public void update() { + WorkerDataEvent dataEvent; + + while(true) { + try{ + // Wait for data to become available + synchronized(getEventQueue()) { + while(getEventQueue().isEmpty()) { + try { + getEventQueue().wait(); + } catch (InterruptedException e) {} + } + dataEvent = (WorkerDataEvent) getEventQueue().remove(0); + } + messageEvent(dataEvent); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public abstract void messageEvent(WorkerDataEvent e); + +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/page/MonitorWebPage.java b/src/zutil/net/nio/worker/Worker.java similarity index 50% rename from plugins/hal-nvr/src/se/hal/plugin/nvr/page/MonitorWebPage.java rename to src/zutil/net/nio/worker/Worker.java index b2a5606f..81cd1d40 100644 --- a/plugins/hal-nvr/src/se/hal/plugin/nvr/page/MonitorWebPage.java +++ b/src/zutil/net/nio/worker/Worker.java @@ -1,58 +1,76 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.nvr.page; - -import se.hal.HalContext; -import se.hal.intf.HalWebPage; -import se.hal.plugin.nvr.struct.Camera; -import zutil.db.DBConnection; -import zutil.io.file.FileUtil; -import zutil.parser.Templator; - -import java.util.List; -import java.util.Map; - -public class MonitorWebPage extends HalWebPage { - private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/camera_monitor.tmpl"; - - public MonitorWebPage() { - super("camera_monitor"); - super.getRootNav().createSubNav("Surveillance").createSubNav(this.getId(), "Monitoring").setWeight(-100); - } - - @Override - public Templator httpRespond(Map session, Map cookie, Map request) throws Exception { - DBConnection db = HalContext.getDB(); - - Templator tmpl = new Templator(FileUtil.find(TEMPLATE)); - - List cameras = Camera.getCameras(db); - for (int i = 0; i < cameras.size(); i++) { - tmpl.set("camera" + (i+1), cameras.get(i)); - } - - return tmpl; - } -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker; + +import zutil.net.nio.NioNetwork; + +import java.nio.channels.SocketChannel; +import java.util.LinkedList; +import java.util.List; + + +public abstract class Worker implements Runnable { + private LinkedList queue = new LinkedList(); + + public void processData(NioNetwork server, SocketChannel socket, Object data) { + synchronized(queue) { + queue.add(new WorkerDataEvent(server, socket, data)); + queue.notify(); + } + } + + /** + * @return The event queue + */ + protected List getEventQueue(){ + return queue; + } + + /** + * @return If there is a event in the queue + */ + protected boolean hasEvent(){ + return !queue.isEmpty(); + } + + /** + * Polls a event from the list or waits until there is a event + * @return The next event + */ + protected WorkerDataEvent pollEvent(){ + while(queue.isEmpty()) { + try { + this.wait(); + } catch (InterruptedException e) {} + } + return queue.poll(); + } + + public void run(){ + update(); + } + + public abstract void update(); +} diff --git a/src/zutil/net/nio/worker/WorkerDataEvent.java b/src/zutil/net/nio/worker/WorkerDataEvent.java new file mode 100644 index 00000000..38f1f7fb --- /dev/null +++ b/src/zutil/net/nio/worker/WorkerDataEvent.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker; + +import zutil.net.nio.NioNetwork; + +import java.nio.channels.SocketChannel; + + +public class WorkerDataEvent { + public NioNetwork network; + public SocketChannel socket; + public Object data; + + public WorkerDataEvent(NioNetwork server, SocketChannel socket, Object data) { + this.network = server; + this.socket = socket; + this.data = data; + } +} diff --git a/src/zutil/net/nio/worker/grid/GridClient.java b/src/zutil/net/nio/worker/grid/GridClient.java new file mode 100644 index 00000000..efb78108 --- /dev/null +++ b/src/zutil/net/nio/worker/grid/GridClient.java @@ -0,0 +1,138 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker.grid; + +import zutil.io.MultiPrintStream; +import zutil.net.nio.NioClient; +import zutil.net.nio.message.GridMessage; +import zutil.net.nio.worker.ThreadedEventWorker; +import zutil.net.nio.worker.WorkerDataEvent; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.Queue; + +/** + * This class is the client part of the grid. + * It connects to a grid server and requests new job. + * And then sends back the result to the server. + * + * @author Ziver + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class GridClient extends ThreadedEventWorker { + private static LinkedList jobQueue; + private static GridThread thread; + private static NioClient network; + + /** + * Creates a new GridClient object and registers itself at the server + * and sets itself as a worker in NioClient + * + * @param thread the Thread interface to run for the jobs + * @param network the NioClient to use to communicate to the server + */ + public GridClient(GridThread thread, NioClient network){ + jobQueue = new LinkedList(); + GridClient.thread = thread; + GridClient.network = network; + + } + + /** + * Starts up the client and a couple of GridThreads. + * And registers itself as a worker in NioClient + * @throws IOException + */ + public void initiate() throws IOException{ + network.setDefaultWorker(this); + network.send(new GridMessage(GridMessage.REGISTER)); + + for(int i=0; i { + /** + * @return static and final values that do not change for every job + */ + public Object initValues(); + /** + * @return a new generated job + */ + public T generateJob(); +} diff --git a/src/zutil/net/nio/worker/grid/GridResultHandler.java b/src/zutil/net/nio/worker/grid/GridResultHandler.java new file mode 100644 index 00000000..61d8b8bb --- /dev/null +++ b/src/zutil/net/nio/worker/grid/GridResultHandler.java @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker.grid; + +/** + * Handles the incoming results from the grid + * + * @author Ziver + */ +public interface GridResultHandler { + + public void resultEvent(int jobID, boolean correct, T result); +} diff --git a/src/zutil/net/nio/worker/grid/GridServerWorker.java b/src/zutil/net/nio/worker/grid/GridServerWorker.java new file mode 100644 index 00000000..0efefea8 --- /dev/null +++ b/src/zutil/net/nio/worker/grid/GridServerWorker.java @@ -0,0 +1,135 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker.grid; + +import zutil.net.nio.message.GridMessage; +import zutil.net.nio.worker.ThreadedEventWorker; +import zutil.net.nio.worker.WorkerDataEvent; + +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Queue; + +/** + * Implements a simple network computing server + * + * @author Ziver + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class GridServerWorker extends ThreadedEventWorker{ + // Job timeout after 30 min + public static int JOB_TIMEOUT = 1000*60*30; + + private HashMap jobs; // contains all the ongoing jobs + private Queue reSendjobQueue; // Contains all the jobs that will be recalculated + private GridJobGenerator jobGenerator; // The job generator + private GridResultHandler resHandler; + private int nextJobID; + + public GridServerWorker(GridResultHandler resHandler, GridJobGenerator jobGenerator){ + this.resHandler = resHandler; + this.jobGenerator = jobGenerator; + nextJobID = 0; + + jobs = new HashMap(); + reSendjobQueue = new LinkedList(); + GridMaintainer maintainer = new GridMaintainer(); + maintainer.start(); + } + + @Override + public void messageEvent(WorkerDataEvent e) { + try { + // ignores other messages than GridMessage + if(e.data instanceof GridMessage){ + GridMessage msg = (GridMessage)e.data; + GridJob job = null; + + switch(msg.messageType()){ + case GridMessage.REGISTER: + e.network.send(e.socket, new GridMessage(GridMessage.INIT_DATA, 0, jobGenerator.initValues())); + break; + // Sending new data to compute to the client + case GridMessage.NEW_DATA: + if(!reSendjobQueue.isEmpty()){ // checks first if there is a job for recalculation + job = reSendjobQueue.poll(); + job.renewTimeStamp(); + } + else{ // generates new job + job = new GridJob(nextJobID, + jobGenerator.generateJob()); + jobs.put(job.jobID, job); + nextJobID++; + } + GridMessage newMsg = new GridMessage(GridMessage.COMP_DATA, job.jobID, job.job); + e.network.send(e.socket, newMsg); + break; + + // Received computation results + case GridMessage.COMP_SUCCESSFUL: + resHandler.resultEvent(msg.getJobQueueID(), true, msg.getData()); + break; + case GridMessage.COMP_INCORRECT: + resHandler.resultEvent(msg.getJobQueueID(), false, msg.getData()); + break; + case GridMessage.COMP_ERROR: // marks the job for recalculation + job = jobs.get(msg.getJobQueueID()); + reSendjobQueue.add(job); + break; + } + } + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + /** + * Changes the job timeout value + * @param min is the timeout in minutes + */ + public static void setJobTimeOut(int min){ + JOB_TIMEOUT = 1000*60*min; + } + + class GridMaintainer extends Thread{ + /** + * Runs some behind the scenes stuff + * like job timeout. + */ + public void run(){ + while(true){ + long time = System.currentTimeMillis(); + for(int jobID : jobs.keySet()){ + if(time-jobs.get(jobID).timestamp > JOB_TIMEOUT){ + reSendjobQueue.add(jobs.get(jobID)); + } + } + try{Thread.sleep(1000*60*1);}catch(Exception e){}; + } + } + } +} + diff --git a/src/zutil/net/nio/worker/grid/GridThread.java b/src/zutil/net/nio/worker/grid/GridThread.java new file mode 100644 index 00000000..240a887d --- /dev/null +++ b/src/zutil/net/nio/worker/grid/GridThread.java @@ -0,0 +1,62 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio.worker.grid; + +/** + * This interface is the thread that will do + * all the computation in the grid + * + * @author Ziver + */ +public abstract class GridThread implements Runnable{ + /** + * The initial static and final data will be sent to this + * method. + * + * @param data is the static and or final data + */ + public abstract void setInitData(Object data); + + public void run(){ + while(true){ + GridJob tmp = null; + try { + tmp = GridClient.getNextJob(); + compute(tmp); + } catch (Exception e) { + e.printStackTrace(); + if(tmp != null){ + GridClient.jobError(tmp.jobID); + } + } + } + } + + /** + * Compute the given data and return + * @param data + */ + public abstract void compute(GridJob data) throws Exception; +} diff --git a/src/zutil/net/ssdp/SSDPClient.java b/src/zutil/net/ssdp/SSDPClient.java new file mode 100755 index 00000000..03626fc9 --- /dev/null +++ b/src/zutil/net/ssdp/SSDPClient.java @@ -0,0 +1,249 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ssdp; + +import zutil.io.StringOutputStream; +import zutil.log.LogUtil; +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpHeaderParser; +import zutil.net.http.HttpPrintStream; +import zutil.net.threaded.ThreadedUDPNetwork; +import zutil.net.threaded.ThreadedUDPNetworkThread; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * An SSDP client class that will request + * service information. + * + * @author Ziver + */ +public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetworkThread{ + private static final Logger logger = LogUtil.getLogger(); + /** Mapping of search targets and list of associated services **/ + private HashMap> services_st; + /** Map of all unique services received **/ + private HashMap services_usn; + + private SSDPServiceListener listener; + + + /** + * Creates new instance of this class. An UDP + * listening socket at the SSDP port. + * + * @throws IOException + */ + public SSDPClient() throws IOException{ + super(null); + super.setThread(this); + + services_st = new HashMap<>(); + services_usn = new HashMap<>(); + } + + /** + * Sends an request for an service + * + * @param searchTarget is the SearchTarget of the service + * + * ***** REQUEST: + * M-SEARCH * HTTP/1.1 + * Host: 239.255.255.250:reservedSSDPport + * Man: "ssdp:discover" + * ST: ge:fridge + * MX: 3 + * + */ + public void requestService(String searchTarget){ + requestService(searchTarget, null); + } + public void requestService(String searchTarget, HashMap headers){ + try { + // Generate an SSDP discover message + StringOutputStream msg = new StringOutputStream(); + HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HttpMessageType.REQUEST ); + http.setRequestType("M-SEARCH"); + http.setRequestURL("*"); + http.setHeader("Host", SSDPServer.SSDP_MULTICAST_ADDR +":"+ SSDPServer.SSDP_PORT ); + http.setHeader("ST", searchTarget ); + http.setHeader("Man", "\"ssdp:discover\"" ); + http.setHeader("MX", "3" ); + if(headers != null) { + for (String key : headers.keySet()) { + http.setHeader(key, headers.get(key)); + } + } + logger.log(Level.FINEST, "Sending Multicast: "+ http); + http.flush(); + + byte[] data = msg.toString().getBytes(); + DatagramPacket packet = new DatagramPacket( + data, data.length, + InetAddress.getByName( SSDPServer.SSDP_MULTICAST_ADDR ), + SSDPServer.SSDP_PORT ); + super.send( packet ); + http.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Set a listener that will be notified when new services are detected + */ + public void setListener(SSDPServiceListener listener){ + this.listener = listener; + } + + /** + * Returns a list of received services by + * the given search target. + * + * @param searchTarget is the search target + * @return a list of received services + */ + public LinkedList getServices(String searchTarget){ + if(services_st.get(searchTarget) == null) + return new LinkedList<>(); + return services_st.get(searchTarget); + } + + /** + * Returns the amount of services in the search target + * + * @param searchTarget is the search target + * @return the amount of services cached + */ + public int getServicesCount(String searchTarget){ + if(services_st.containsKey(searchTarget)){ + return services_st.get(searchTarget).size(); + } + return 0; + } + + /** + * Returns a service with the given USN. + * + * @param usn is the unique identifier for a service + * @return an service, null if there is no such service + */ + public StandardSSDPInfo getService(String usn){ + return services_usn.get( usn ); + } + + /** + * Clears all the received information of the services + */ + public void clearServices(){ + services_usn.clear(); + services_st.clear(); + } + /** + * Clears all services matching the search target + */ + public void clearServices(String st){ + if(services_st.get(st) != null) { + for (StandardSSDPInfo service : services_st.get(st)) { + services_usn.remove(service.getUSN()); + } + } + } + + /** + * Waits for responses + * + * ***** RESPONSE; + * HTTP/1.1 200 OK + * Ext: + * Cache-Control: no-cache="Ext", max-age = 5000 + * ST: ge:fridge + * USN: uuid:abcdefgh-7dec-11d0-a765-00a0c91e6bf6 + * Location: http://localhost:80 + */ + public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) { + try { + String msg = new String(packet.getData(), packet.getOffset(), packet.getLength()); + HttpHeaderParser headerParser = new HttpHeaderParser(msg); + HttpHeader header = headerParser.read(); + logger.log(Level.FINEST, "Received(from: " + packet.getAddress() + "): " + header); + + String usn = header.getHeader("USN"); + String st = header.getHeader("ST"); + boolean newService = false; + StandardSSDPInfo service; + // Get existing service + if (services_usn.containsKey(usn)) { + service = services_usn.get(usn); + } + // Add new service + else { + newService = true; + service = new StandardSSDPInfo(); + services_usn.put(usn, service); + if (!services_st.containsKey(st)) + services_st.put(st, new LinkedList()); + services_st.get(header.getHeader("ST")).add(service); + } + + service.setLocation(header.getHeader("LOCATION")); + service.setST(st); + service.setUSN(usn); + service.setInetAddress(packet.getAddress()); + if (header.getHeader("Cache-Control") != null) { + service.setExpirationTime( + System.currentTimeMillis() + 1000 * getCacheTime(header.getHeader("Cache-Control"))); + } + service.readHeaders(header); + + if (listener != null && newService) + listener.newService(service); + } catch (IOException e){ + logger.log(Level.SEVERE, null, e); + } + } + + private long getCacheTime(String cache_control){ + long ret = 0; + String[] tmp = cache_control.split(","); + for( String element : tmp ){ + element = element.replaceAll("\\s", "").toLowerCase(); + if( element.startsWith("max-age=") ){ + ret = Long.parseLong( element.substring( "max-age=".length() ) ); + } + } + return ret; + } + + public interface SSDPServiceListener{ + public void newService(StandardSSDPInfo service); + } +} diff --git a/src/zutil/net/ssdp/SSDPCustomInfo.java b/src/zutil/net/ssdp/SSDPCustomInfo.java new file mode 100755 index 00000000..e74be91d --- /dev/null +++ b/src/zutil/net/ssdp/SSDPCustomInfo.java @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ssdp; + +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpPrintStream; + +/** + * Created by Ziver on 2014-11-07. + */ +public interface SSDPCustomInfo extends SSDPServiceInfo{ + + public void readHeaders(HttpHeader http); + + public void writeHeaders(HttpPrintStream http); +} diff --git a/src/zutil/net/ssdp/SSDPServer.java b/src/zutil/net/ssdp/SSDPServer.java new file mode 100755 index 00000000..457a97f8 --- /dev/null +++ b/src/zutil/net/ssdp/SSDPServer.java @@ -0,0 +1,336 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ssdp; + +import zutil.StringUtil; +import zutil.io.StringOutputStream; +import zutil.log.LogUtil; +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpHeaderParser; +import zutil.net.http.HttpPrintStream; +import zutil.net.threaded.ThreadedUDPNetwork; +import zutil.net.threaded.ThreadedUDPNetworkThread; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Timer; +import java.util.TimerTask; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A Server class that announces an service by the SSDP + * protocol specified at: + * http://coherence.beebits.net/chrome/site/draft-cai-ssdp-v1-03.txt + * ftp://ftp.pwg.org/pub/pwg/www/hypermail/ps/att-0188/01-psi_SSDP.pdf + * + * @author Ziver + * + * ********* Message clarification: + * ****** Incoming: + * ST: Search Target, this is object of the discovery request, (e.g., ssdp:all, etc.) + * HOST: This is the SSDP multicast address + * MAN: Description of packet type, (e.g., "ssdp:discover", ) + * MX: Wait these few seconds and then send response + * + * ****** Outgoing: + * EXT: required by HTTP - not used with SSDP + * SERVER: informational + * LOCATION: This is the URL to request the QueryEndpointsInterface endpoint + * USN: advertisement UUID + * CACHE-CONTROL: max-age = seconds until advertisement expires + * NT: Notify target same as ST + * NTS: same as Man but for Notify messages + */ +public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetworkThread{ + private static final Logger logger = LogUtil.getLogger(); + public static final String SERVER_INFO = "Zutil SSDP Java Server"; + public static final int DEFAULT_CACHE_TIME = 60*30; // 30 min + public static final int BUFFER_SIZE = 512; + public static final String SSDP_MULTICAST_ADDR = "239.255.255.250"; + public static final int SSDP_PORT = 1900; + + // instance specific values + private int cache_time; + private NotifyTimer notifyTimer = null; + /** HashMap that contains services as < SearchTargetName, SSDPServiceInfo > */ + private HashMap services; + + + + public SSDPServer() throws IOException{ + super( null, SSDP_MULTICAST_ADDR, SSDP_PORT ); + super.setThread( this ); + + services = new HashMap(); + + setCacheTime( DEFAULT_CACHE_TIME ); + enableNotify( true ); + } + + /** + * Adds an service that will be announced. + * + * @param service add a new service to be announced + */ + public void addService(SSDPServiceInfo service){ + services.put( service.getSearchTarget(), service ); + } + /** + * Remove a service from being announced. This function will + * send out an byebye message to the clients that the service is down. + * + * @param searchTarget is the ST value in SSDP + */ + public void removeService(String searchTarget){ + sendByeBye( searchTarget ); + services.remove( searchTarget ); + } + + /** + * Sets the cache time that will be sent to + * the clients. If notification is enabled then an + * notification message will be sent every cache_time/2 seconds + * + * @param time is the time in seconds + */ + public void setCacheTime(int time){ + cache_time = time; + if( isNotifyEnabled() ){ + enableNotify(false); + enableNotify(true); + } + } + + /** + * Enable or disable notification messages to clients + * every cache_time/2 seconds + */ + public void enableNotify(boolean enable){ + if( enable && notifyTimer==null ){ + notifyTimer = new NotifyTimer(); + Timer timer = new Timer(); + timer.schedule(new NotifyTimer(), 0, cache_time*1000/2); + }else if( !enable && notifyTimer!=null ){ + notifyTimer.cancel(); + notifyTimer = null; + } + } + /** + * @return if notification messages is enabled + */ + public boolean isNotifyEnabled(){ + return notifyTimer != null; + } + + /** + * Handles the incoming packets like this: + * + * ***** REQUEST: + * M-SEARCH * HTTP/1.1 + * Host: 239.255.255.250:reservedSSDPport + * Man: "ssdp:discover" + * ST: ge:fridge + * MX: 3 + * + * ***** RESPONSE; + * HTTP/1.1 200 OK + * Ext: + * Cache-Control: no-cache="Ext", max-age = 5000 + * ST: ge:fridge + * USN: uuid:abcdefgh-7dec-11d0-a765-00a0c91e6bf6 + * Location: http://localhost:80 + * + */ + public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) { + try { + String msg = new String( packet.getData(), packet.getOffset(), packet.getLength() ); + HttpHeaderParser headerParser = new HttpHeaderParser( msg ); + HttpHeader header = headerParser.read(); + + // ******* Respond + // Check that the message is an ssdp discovery message + if( header.getRequestType() != null && header.getRequestType().equalsIgnoreCase("M-SEARCH") ){ + String man = header.getHeader("Man"); + if(man != null) + man = StringUtil.trim(man, '\"'); + String st = header.getHeader("ST"); + // Check that its the correct URL and that its an ssdp:discover message + if( header.getRequestURL().equals("*") && "ssdp:discover".equalsIgnoreCase(man) ){ + // Check if the requested service exists + if( services.containsKey( st ) ){ + logger.log(Level.FINEST, "Received Multicast(from: "+packet.getAddress()+"): "+ header); + + // Generate the SSDP response + StringOutputStream response = new StringOutputStream(); + HttpPrintStream http = new HttpPrintStream( response ); + http.setStatusCode(200); + http.setHeader("Location", services.get(st).getLocation() ); + http.setHeader("USN", services.get(st).getUSN() ); + http.setHeader("Server", SERVER_INFO ); + http.setHeader("ST", st ); + http.setHeader("EXT", "" ); + http.setHeader("Cache-Control", "max-age = "+ cache_time ); + if(services.get(st) instanceof SSDPCustomInfo) + ((SSDPCustomInfo)services.get(st)).writeHeaders(http); + logger.log(Level.FINEST, "Sending Response: "+ http); + http.flush(); + + String strData = response.toString(); + byte[] data = strData.getBytes(); + packet = new DatagramPacket( + data, data.length, + packet.getAddress(), + packet.getPort()); + network.send( packet ); + http.close(); + } + } + } + } catch (IOException e) { + logger.log(Level.SEVERE, null, e); + } + } + + + /** + * This thread is a timer task that sends an + * notification message to the network every + * cache_time/2 seconds. + * + * @author Ziver + */ + private class NotifyTimer extends TimerTask { + public void run(){ + sendNotify(); + } + } + /** + * Sends keep-alive messages to update the cache of the clients + */ + public void sendNotify(){ + for(String st : services.keySet()){ + sendNotify( st ); + } + } + /** + * Sends an keepalive message to update the cache of the clients + * + * @param searchTarget is the ST value of the service + * + * ********** Message ex: + * NOTIFY * HTTP/1.1 + * Host: 239.255.255.250:reservedSSDPport + * NT: blenderassociation:blender + * NTS: ssdp:alive + * USN: someunique:idscheme3 + * Location: http://localhost:80 + * Cache-Control: max-age = 7393 + */ + public void sendNotify(String searchTarget){ + try { + SSDPServiceInfo service = services.get(searchTarget); + // Generate the SSDP response + StringOutputStream msg = new StringOutputStream(); + HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HttpMessageType.REQUEST ); + http.setRequestType("NOTIFY"); + http.setRequestURL("*"); + http.setHeader("Server", SERVER_INFO ); + http.setHeader("Host", SSDP_MULTICAST_ADDR+":"+SSDP_PORT ); + http.setHeader("NT", searchTarget ); + http.setHeader("NTS", "ssdp:alive" ); + http.setHeader("Location", service.getLocation() ); + http.setHeader("Cache-Control", "max-age = "+cache_time ); + http.setHeader("USN", service.getUSN() ); + if(service instanceof SSDPCustomInfo) + ((SSDPCustomInfo) service).writeHeaders(http); + logger.log(Level.FINEST, "Sending Notification: " + http); + http.flush(); + + byte[] data = msg.toString().getBytes(); + DatagramPacket packet = new DatagramPacket( + data, data.length, + InetAddress.getByName( SSDP_MULTICAST_ADDR ), + SSDP_PORT ); + super.send( packet ); + http.close(); + + } catch (Exception e) { + logger.log(Level.SEVERE, null, e); + } + } + + + /** + * Shutdown message is sent to the clients that all + * the service is shutting down. + */ + public void sendByeBye(){ + for(String st : services.keySet()){ + sendByeBye( st ); + } + } + /** + * Shutdown message is sent to the clients that the service is shutting down + * + * @param searchTarget is the ST value of the service + * + * ********** Message ex: + * NOTIFY * HTTP/1.1 + * Host: 239.255.255.250:reservedSSDPport + * NT: someunique:idscheme3 + * NTS: ssdp:byebye + * USN: someunique:idscheme3 + */ + public void sendByeBye(String searchTarget){ + try { + // Generate the SSDP response + StringOutputStream msg = new StringOutputStream(); + HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HttpMessageType.REQUEST ); + http.setRequestType("NOTIFY"); + http.setRequestURL("*"); + http.setHeader("Server", SERVER_INFO ); + http.setHeader("Host", SSDP_MULTICAST_ADDR+":"+SSDP_PORT ); + http.setHeader("NT", searchTarget ); + http.setHeader("NTS", "ssdp:byebye" ); + http.setHeader("USN", services.get(searchTarget).getUSN() ); + logger.log(Level.FINEST, "Sending ByeBye: " + http); + http.flush(); + + byte[] data = msg.toString().getBytes(); + DatagramPacket packet = new DatagramPacket( + data, data.length, + InetAddress.getByName( SSDP_MULTICAST_ADDR ), + SSDP_PORT ); + super.send( packet ); + http.close(); + + } catch (Exception e) { + logger.log(Level.SEVERE, null, e); + } + } +} diff --git a/src/zutil/net/ssdp/SSDPServiceInfo.java b/src/zutil/net/ssdp/SSDPServiceInfo.java new file mode 100755 index 00000000..4131957a --- /dev/null +++ b/src/zutil/net/ssdp/SSDPServiceInfo.java @@ -0,0 +1,59 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ssdp; + +/** + * This class contains information about a service from + * or through the SSDP protocol + * + * @author Ziver + */ +public interface SSDPServiceInfo { + + /** + * @return the URL to the Service, e.g. "http://192.168.0.1:80/index.html" + */ + public String getLocation(); + + /** + * @return the Search Target, e.g. "upnp:rootdevice" + */ + public String getSearchTarget(); + + /** + * @return the expiration time for the values in this object + */ + public long getExpirationTime(); + + /** + * @return the USN value, e.g. "uuid:abcdefgh-7dec-11d0-a765-00a0c91e6bf6 " + */ + public String getUSN(); + + /** + * @return only the USN UUID String + */ + public String getUUID(); +} diff --git a/src/zutil/net/ssdp/StandardSSDPInfo.java b/src/zutil/net/ssdp/StandardSSDPInfo.java new file mode 100755 index 00000000..644a85d6 --- /dev/null +++ b/src/zutil/net/ssdp/StandardSSDPInfo.java @@ -0,0 +1,164 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ssdp; + +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpPrintStream; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.UUID; + +/** + * This class contains information about a service from + * or through the SSDP protocol + * + * @author Ziver + */ +public class StandardSSDPInfo implements SSDPServiceInfo, SSDPCustomInfo{ + private String location; + private String st; + private String usn; + private long expiration_time; + // All header parameters + private HashMap headers = new HashMap<>(); + private InetAddress inetAddress; + + /** + * @param l is the value to set the Location variable + */ + public void setLocation(String l) { + location = l; + } + + /** + * @param st is the value to set the SearchTarget variable + */ + public void setST(String st) { + this.st = st; + } + + /** + * @param usn is the value to set the USN variable + */ + protected void setUSN(String usn) { + this.usn = usn; + } + + /** + * @param time sets the expiration time of values in this object + */ + protected void setExpirationTime(long time) { + expiration_time = time; + } + + /** + * @return The URL to the Service, e.g. "http://192.168.0.1:80/index.html" + */ + public String getLocation(){ + return location; + } + + /** + * @return the Search Target, e.g. "upnp:rootdevice" + */ + public String getSearchTarget(){ + return st; + } + + /** + * @return the expiration time for the values in this object + */ + public long getExpirationTime(){ + return expiration_time; + } + + /** + * @return the USN value, e.g. "uuid:abcdefgh-7dec-11d0-a765-00a0c91e6bf6 " + */ + public String getUSN(){ + if( usn==null ) + usn = genUSN(); + return usn+"::"+st; + } + + /** + * @return only the USN UUID String + */ + public String getUUID(){ + if( usn==null ) + usn = genUSN(); + return usn; + } + + /** + * Generates an unique USN for the service + * + * @return an unique string that corresponds to the service + */ + private String genUSN(){ + return "uuid:" + UUID.nameUUIDFromBytes( (st+location+Math.random()).getBytes() ); + } + + public String toString(){ + return "USN: "+usn+"\nLocation: "+location+"\nST: "+st+"\nExpiration-Time: "+new Date(expiration_time); + } + + + public void setHeader(String key, String value) { + headers.put(key, value); + } + public String getHeader(String header){ + return headers.get(header); + } + @Override + public void writeHeaders(HttpPrintStream http) { + try { + for (String key : headers.keySet()) + http.setHeader(key, headers.get(key)); + }catch(IOException e){ + e.printStackTrace(); + } + } + @Override + public void readHeaders(HttpHeader header) { + Iterator it = header.getHeaderKeys(); + while (it.hasNext()) { + String key = it.next(); + headers.put(key, header.getHeader(key)); + } + } + + public InetAddress getInetAddress(){ + return inetAddress; + } + + protected void setInetAddress(InetAddress inetAddress) { + this.inetAddress = inetAddress; + } +} diff --git a/src/zutil/net/threaded/ThreadedTCPNetworkServer.java b/src/zutil/net/threaded/ThreadedTCPNetworkServer.java new file mode 100644 index 00000000..9f7e3e1e --- /dev/null +++ b/src/zutil/net/threaded/ThreadedTCPNetworkServer.java @@ -0,0 +1,149 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.threaded; + +import zutil.log.LogUtil; + +import javax.net.ssl.SSLServerSocketFactory; +import java.io.File; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateException; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * A simple network server that handles TCP communication + * + * @author Ziver + */ +public abstract class ThreadedTCPNetworkServer extends Thread{ + private static final Logger logger = LogUtil.getLogger(); + + public final int port; + private File keyStore; + private String keyStorePass; + + /** + * Creates a new instance of the sever + * + * @param port The port that the server should listen to + */ + public ThreadedTCPNetworkServer(int port){ + this(port, null, null); + } + /** + * Creates a new instance of the sever + * + * @param port The port that the server should listen to + * @param sslCert If this is not null then the server will use SSL connection with this keyStore file path + * @param sslCert If this is not null then the server will use a SSL connection with the given certificate + */ + public ThreadedTCPNetworkServer(int port, File keyStore, String keyStorePass){ + this.port = port; + this.keyStorePass = keyStorePass; + this.keyStore = keyStore; + } + + + public void run(){ + ServerSocket ss = null; + try{ + if(keyStorePass != null && keyStore != null){ + registerCertificate(keyStore, keyStorePass); + ss = initSSL( port ); + } + else{ + ss = new ServerSocket( port ); + } + logger.info("Listening for TCP Connections on port: "+port); + + while(true){ + Socket s = ss.accept(); + ThreadedTCPNetworkServerThread t = getThreadInstance( s ); + if( t!=null ) + new Thread( t ).start(); + else{ + logger.severe("Unable to instantiate ThreadedTCPNetworkServerThread, closing connection!"); + s.close(); + } + } + } catch(Exception e) { + logger.log(Level.SEVERE, null, e); + } finally { + if( ss!=null ){ + try{ + ss.close(); + }catch(IOException e){ logger.log(Level.SEVERE, null, e); } + } + } + } + + /** + * This method returns an new instance of the ThreadedTCPNetworkServerThread + * that will handle the newly made connection, if an null value is returned + * then the ThreadedTCPNetworkServer will close the new connection. + * + * @param s is an new connection to an host + * @return a new instance of an thread or null + */ + protected abstract ThreadedTCPNetworkServerThread getThreadInstance( Socket s ); + + /** + * Initiates a SSLServerSocket + * + * @param port The port to listen to + * @return The SSLServerSocket + */ + private ServerSocket initSSL(int port) throws IOException{ + SSLServerSocketFactory sslserversocketfactory = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + return sslserversocketfactory.createServerSocket(port); + + } + + /** + * Registers the given cert file to the KeyStore + * + * @param certFile The cert file + */ + protected void registerCertificate(File keyStore, String keyStorePass) throws CertificateException, IOException, KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException{ + System.setProperty("javax.net.ssl.keyStore", keyStore.getAbsolutePath()); + System.setProperty("javax.net.ssl.keyStorePassword", keyStorePass); + } + + /** + * Stops the server and interrupts its internal thread. + * This is a permanent action that will not be able to recover from + */ + public void close(){ + this.interrupt(); + } +} diff --git a/src/zutil/net/threaded/ThreadedTCPNetworkServerThread.java b/src/zutil/net/threaded/ThreadedTCPNetworkServerThread.java new file mode 100644 index 00000000..59e98109 --- /dev/null +++ b/src/zutil/net/threaded/ThreadedTCPNetworkServerThread.java @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.threaded; + +/** + * The class that will handle the a TCP connection will include + * this interface + * + * @author Ziver + * + */ +public interface ThreadedTCPNetworkServerThread extends Runnable{ + +} diff --git a/src/zutil/net/threaded/ThreadedUDPNetwork.java b/src/zutil/net/threaded/ThreadedUDPNetwork.java new file mode 100644 index 00000000..4087e7c9 --- /dev/null +++ b/src/zutil/net/threaded/ThreadedUDPNetwork.java @@ -0,0 +1,142 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.threaded; + +import java.io.IOException; +import java.net.*; + + + +/** + * * A simple network server that handles UDP communication + * + * @author Ziver + */ +public class ThreadedUDPNetwork extends Thread{ + public static final int BUFFER_SIZE = 512; + + // Type of UDP socket + enum UDPType{ + MULTICAST, + UNICAST + } + protected final UDPType type; + protected final int port; + protected DatagramSocket socket; + protected ThreadedUDPNetworkThread thread = null; + + /** + * Creates a new unicast Client instance of the class + * + * @param thread is the class that will handle incoming packets + * @throws SocketException + */ + public ThreadedUDPNetwork(ThreadedUDPNetworkThread thread) throws SocketException{ + this.type = UDPType.UNICAST; + this.port = -1; + setThread( thread ); + + socket = new DatagramSocket(); + } + + /** + * Creates a new unicast Server instance of the class + * + * @param thread is the class that will handle incoming packets + * @param port is the port that the server should listen to + * @throws SocketException + */ + public ThreadedUDPNetwork(ThreadedUDPNetworkThread thread, int port) throws SocketException{ + this.type = UDPType.UNICAST; + this.port = port; + setThread( thread ); + + socket = new DatagramSocket( port ); + } + + /** + * Creates a new multicast Server instance of the class + * + * @param thread is the class that will handle incoming packets + * @param port is the port that the server should listen to + * @param multicast_addr is the multicast address that the server will listen on + * @throws IOException + */ + public ThreadedUDPNetwork(ThreadedUDPNetworkThread thread, String multicast_addr, int port ) throws IOException{ + this.type = UDPType.MULTICAST; + this.port = port; + setThread( thread ); + + // init udp socket + MulticastSocket msocket = new MulticastSocket( port ); + InetAddress group = InetAddress.getByName( multicast_addr ); + msocket.joinGroup( group ); + + socket = msocket; + } + + + public void run(){ + try{ + while(true){ + byte[] buf = new byte[BUFFER_SIZE]; + DatagramPacket packet = new DatagramPacket(buf, buf.length); + socket.receive( packet ); + if( thread!=null ) + thread.receivedPacket( packet, this ); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Sends the given packet + * + * @param packet is the packet to send + * @throws IOException + */ + public synchronized void send( DatagramPacket packet ) throws IOException{ + socket.send(packet); + } + + /** + * Sets the thread that will handle the incoming packets + * + * @param thread is the thread + */ + public void setThread(ThreadedUDPNetworkThread thread){ + this.thread = thread; + } + + /** + * Stops the server and interrupts its internal thread. + * This is a permanent action that will not be able to recover from + */ + public void close(){ + this.interrupt(); + socket.close(); + } +} diff --git a/src/zutil/net/threaded/ThreadedUDPNetworkThread.java b/src/zutil/net/threaded/ThreadedUDPNetworkThread.java new file mode 100644 index 00000000..52bd3c84 --- /dev/null +++ b/src/zutil/net/threaded/ThreadedUDPNetworkThread.java @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.threaded; + +import java.net.DatagramPacket; + +/** + * This interface is for processing received packets + * from the ThreadedUDPNetworkServer + * + * @author Ziver + * + */ +public interface ThreadedUDPNetworkThread extends Runnable{ + + /** + * Packet will be processed in this method + * + * @param packet is the received packet + * @param network is the network class that received the packet + */ + public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network); +} diff --git a/src/zutil/net/torrent/TorrentFile.java b/src/zutil/net/torrent/TorrentFile.java new file mode 100644 index 00000000..66d28fe5 --- /dev/null +++ b/src/zutil/net/torrent/TorrentFile.java @@ -0,0 +1,56 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.torrent; + +import zutil.Dumpable; + +/** + * This class represents a File for download + * + * @author Ziver + */ +public class TorrentFile implements Dumpable{ + private String filename; + private long length; + + public TorrentFile(String filename, long length){ + this.filename = filename; + this.length = length; + } + + + public String getFilename() { + return filename; + } + public void setFilename(String filename) { + this.filename = filename; + } + public long getLength() { + return length; + } + public void setLength(long length) { + this.length = length; + } +} diff --git a/src/zutil/net/torrent/TorrentMetainfo.java b/src/zutil/net/torrent/TorrentMetainfo.java new file mode 100755 index 00000000..d78e2777 --- /dev/null +++ b/src/zutil/net/torrent/TorrentMetainfo.java @@ -0,0 +1,189 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.torrent; + +import zutil.io.MultiPrintStream; +import zutil.io.file.FileUtil; +import zutil.parser.BEncodedParser; +import zutil.parser.DataNode; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +public class TorrentMetainfo { + /** Comment (optional) **/ + private String comment; + /** Signature of the software which created the torrent (optional) **/ + private String created_by; + /** Creation date as Unix timestamp (optional) **/ + private long creation_date; + /** The main Tracker (the tracker the torrent has been received from) **/ + private String announce; + /** List of known trackers for the torrent (optional) **/ + private ArrayList announce_list; + /** The encoding of the Strings (optional) **/ + private String encoding; + + /** Size of of the full torrent (after download) **/ + private long size; + /** Number of bytes in each piece **/ + private long piece_length; + /** String consisting of the concatenation of all 20-byte SHA1 hash values, one per piece **/ + private ArrayList piece_hashes; + /** Torrent is private. No other trackers allowed other then those listed. (optional) **/ + private boolean is_private; + + // Files in the torrent + private ArrayList file_list; + + + + public TorrentMetainfo(File torrent) throws IOException{ + this(FileUtil.getContent(torrent)); + } + + public TorrentMetainfo(String data){ + decode(data); + } + + + private void decode(String data){ + DataNode metainfo = BEncodedParser.read(data); + + // Main values + announce = metainfo.getString("announce"); + created_by = metainfo.getString("created by"); + comment = metainfo.getString("comment"); + encoding = metainfo.getString("encoding"); + if( metainfo.get("creation date") != null ) + creation_date = metainfo.getLong("creation date"); + if( metainfo.get("announce-list") != null ){ + DataNode tmp = metainfo.get("announce-list"); + announce_list = new ArrayList(); + for( DataNode tracker : tmp ) + announce_list.add( tracker.getString() ); + } + + // info data + DataNode info = metainfo.get("info"); + String name = info.getString("name"); + piece_length = info.getLong("piece length"); + if( info.get("private") != null ) + is_private = (info.getInt("private") != 0); + // Split the hashes + String hashes = info.getString("pieces"); + piece_hashes = new ArrayList(); + for(int i=0; i(); + // Single-file torrent + if( info.get("files") == null ){ + Long length = info.getLong("length"); + file_list.add( new TorrentFile(name, length) ); + } + // Multi-file torrent + else{ + DataNode files = info.get("files"); + for( DataNode file : files ){ + String filename = ""; + DataNode tmp = file.get("path"); + // File in subdir + if( tmp.isList() ){ + Iterator it = tmp.iterator(); + while( it.hasNext() ){ + filename += it.next().getString(); + if(it.hasNext()) filename += File.separator; + } + } + // File in root dir + else + filename = tmp.getString(); + Long length = file.getLong("length"); + filename = name + File.separator + filename; + file_list.add( new TorrentFile(filename, length) ); + } + } + } + + + + public String getComment() { + return comment; + } + public String getCreated_by() { + return created_by; + } + public long getCreation_date() { + return creation_date; + } + public String getAnnounce() { + return announce; + } + public ArrayList getAnnounce_list() { + return announce_list; + } + public String getEncoding() { + return encoding; + } + public long getSize() { + return size; + } + public long getPiece_length() { + return piece_length; + } + public ArrayList getPiece_hashes() { + return piece_hashes; + } + public boolean isIs_private() { + return is_private; + } + public ArrayList getFile_list() { + return file_list; + } + + /** + * Example use + */ + public static void main(String[] args){ + try { + TorrentMetainfo tmp = new TorrentMetainfo(FileUtil.find("test.torrent")); + MultiPrintStream.out.dump(tmp); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/zutil/net/torrent/TorrentTracker.java b/src/zutil/net/torrent/TorrentTracker.java new file mode 100755 index 00000000..ae4740ae --- /dev/null +++ b/src/zutil/net/torrent/TorrentTracker.java @@ -0,0 +1,50 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.torrent; + +import zutil.net.http.HttpClient; +import zutil.net.http.HttpHeaderParser; + +import java.io.IOException; +import java.net.URL; + +/** + * This tracker represents a tracker client + * that connects to a tracker + * + * @author Ziver + */ +public class TorrentTracker { + /** The address to the tracker **/ + private URL trackerURL; + + + // TODO: incomplete + public void update() throws IOException { + HttpClient request = new HttpClient(HttpClient.HttpRequestType.GET); + request.setURL( trackerURL ); + HttpHeaderParser response = request.send(); + } +} diff --git a/plugins/hal-powerchallenge/src/se/hal/plugin/powerchallenge/page/PCOverviewWebPage.java b/src/zutil/net/update/FileInfo.java similarity index 51% rename from plugins/hal-powerchallenge/src/se/hal/plugin/powerchallenge/page/PCOverviewWebPage.java rename to src/zutil/net/update/FileInfo.java index f07f4b77..35603a02 100644 --- a/plugins/hal-powerchallenge/src/se/hal/plugin/powerchallenge/page/PCOverviewWebPage.java +++ b/src/zutil/net/update/FileInfo.java @@ -1,64 +1,81 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.powerchallenge.page; - -import se.hal.HalContext; -import se.hal.intf.HalWebPage; -import se.hal.struct.Sensor; -import se.hal.struct.User; -import zutil.db.DBConnection; -import zutil.io.file.FileUtil; -import zutil.parser.Templator; - -import java.util.List; -import java.util.Map; - -public class PCOverviewWebPage extends HalWebPage { - private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/pc_overview.tmpl"; - - public PCOverviewWebPage() { - super("pc_overview"); - super.getRootNav().createSubNav("Sensors").createSubNav(this.getId(), "Power;Challenge").setWeight(50); - } - - @Override - public Templator httpRespond ( - Map session, - Map cookie, - Map request) - throws Exception { - - DBConnection db = HalContext.getDB(); - List sensors = Sensor.getSensors(db); - - Templator tmpl = new Templator(FileUtil.find(TEMPLATE)); - tmpl.set("users", User.getUsers(db)); - tmpl.set("sensors", sensors); - - return tmpl; - } - - -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import zutil.Hasher; +import zutil.io.file.FileUtil; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; + +/** + * This class is used to store the files + * and there hashes + * + * @author Ziver + */ +public class FileInfo implements Serializable{ + private static final long serialVersionUID = 1L; + + private transient File file; + private String path; + private String hash; + private long size; + + public FileInfo(String root, File file) throws IOException{ + path = FileUtil.relativePath(file, root); + hash = Hasher.MD5(file); + size = file.length(); + this.file = file; + } + + + public String getPath() { + return path; + } + public String getHash() { + return hash; + } + public long getSize() { + return size; + } + public File getFile(){ + return file; + } + + + public boolean equals(Object comp){ + if(comp instanceof FileInfo){ + FileInfo tmp = (FileInfo)comp; + return path.equals(tmp.path) && hash.equals(tmp.hash); + } + return false; + } + + public String toString(){ + return path; + } +} diff --git a/src/zutil/net/update/FileListMessage.java b/src/zutil/net/update/FileListMessage.java new file mode 100644 index 00000000..61884e97 --- /dev/null +++ b/src/zutil/net/update/FileListMessage.java @@ -0,0 +1,106 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import zutil.io.file.FileUtil; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to store the files + * and there hashes + * + * @author Ziver + */ +class FileListMessage implements Serializable{ + private static final long serialVersionUID = 1L; + + private ArrayList fileList; + private long totalSize; + + private FileListMessage(){} + + /** + * Returns a ArrayList of FileInfo object for all the files in the specified folder + * + * @param path is the path to scan + **/ + public FileListMessage(String path) throws IOException{ + fileList = new ArrayList(); + + List files = FileUtil.search(FileUtil.find(path)); + long totalSize = 0; + for(File file : files){ + FileInfo fileInfo = new FileInfo(path, file); + fileList.add( fileInfo ); + totalSize += fileInfo.getSize(); + } + this.totalSize = totalSize; + } + + + public long getTotalSize() { + return totalSize; + } + + public ArrayList getFileList(){ + return fileList; + } + + /** + * Compares the files and returns the files that differ from this file list + * + * @param comp is the file list to compare with + * @return + */ + public FileListMessage getDiff( FileListMessage comp){ + FileListMessage diff = new FileListMessage(); + + long diffSize = 0; + diff.fileList = new ArrayList(); + for(FileInfo file : this.fileList){ + if( !comp.fileList.contains( file)){ + diff.fileList.add( file ); + diffSize += file.getSize(); + } + } + diff.totalSize = diffSize; + + return diff; + } + + + public boolean equals(Object comp){ + if(comp instanceof FileListMessage){ + FileListMessage tmp = (FileListMessage)comp; + return fileList.equals(tmp.fileList) && totalSize == tmp.totalSize; + } + return false; + } +} diff --git a/src/zutil/net/update/UpdateClient.java b/src/zutil/net/update/UpdateClient.java new file mode 100644 index 00000000..25f9fe4a --- /dev/null +++ b/src/zutil/net/update/UpdateClient.java @@ -0,0 +1,174 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import zutil.ProgressListener; +import zutil.io.file.FileUtil; +import zutil.log.LogUtil; + +import java.io.*; +import java.net.Socket; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class connects to a update server and updates a path + * with the servers + * + * @author Ziver + * + */ +public class UpdateClient{ + private static final Logger logger = LogUtil.getLogger(); + + private String path; + private Socket socket; + private FileListMessage fileList; + + private long speed; + private long totalReceived; + private long expectedSize; + private ProgressListener progress; + + /** + * Creates a UpdateClient + * + * @param address Address to the UpdateServer + * @param port The port on the server + * @param path Path to the files to update + * @throws Exception + */ + public UpdateClient(String address, int port, String path) throws Exception{ + fileList = new FileListMessage(path); + socket = new Socket(address, port); + this.path = path; + } + + public void setProgressListener(ProgressListener p){ + progress = p; + } + + /** + * Updates the files + */ + public void update() throws IOException{ + try{ + ObjectOutputStream out = new ObjectOutputStream( socket.getOutputStream()); + ObjectInputStream in = new ObjectInputStream ( socket.getInputStream() ); + + // send client file list + out.writeObject( fileList ); + out.flush(); + // get update list + FileListMessage updateList = (FileListMessage) in.readObject(); + expectedSize = updateList.getTotalSize(); + + // receive file updates + File tmpPath = FileUtil.find(path); + totalReceived = 0; + for(FileInfo info : updateList.getFileList() ){ + // reading new file data + File file = new File( tmpPath, info.getPath() ); + logger.fine("Updating file: "+file); + if( !file.getParentFile().exists() && !file.getParentFile().mkdirs() ){ + throw new IOException("Unable to create folder: "+file.getParentFile()); + } + File tmpFile = File.createTempFile(file.getName(), ".tmp", tmpPath); + tmpFile.deleteOnExit(); + + FileOutputStream fileOut = new FileOutputStream(tmpFile); + byte[] buffer = new byte[socket.getReceiveBufferSize()]; + + long bytesReceived = 0; + int byteRead = 0; + long time = System.currentTimeMillis(); + long timeTotalRecived = 0; + + while( bytesReceived < info.getSize() ) { + byteRead = in.read(buffer); + fileOut.write(buffer, 0, byteRead); + bytesReceived += byteRead; + + if(time+1000 < System.currentTimeMillis()){ + time = System.currentTimeMillis(); + speed = (int)(totalReceived - timeTotalRecived); + timeTotalRecived = totalReceived; + } + + totalReceived += byteRead; + if(progress != null) progress.progressUpdate(this, info, ((double)totalReceived/updateList.getTotalSize())*100); + } + fileOut.close(); + speed = 0; + + // delete old file and replace whit new + file.delete(); + if( !tmpFile.renameTo(file) ){ + throw new IOException("Can not move downloaded file: "+tmpFile.getAbsolutePath()+" to: "+file); + } + } + }catch(ClassNotFoundException e){ + logger.log(Level.SEVERE, null, e); + } + + logger.info("Update done."); + } + + /** + * Returns the speed of the transfer + * + * @return The speed in bytes/s + */ + public long getSpeed(){ + return speed; + } + + /** + * Returns the total amount of data received + * + * @return a long that represents bytes + */ + public long getTotalReceived(){ + return totalReceived; + } + + /** + * Returns the expected total amount of data that will be received + * + * @return a long that represents bytes + */ + public long getTotalSize(){ + return expectedSize; + } + + /** + * Closes the connection + * + * @throws IOException + */ + public void close() throws IOException{ + socket.close(); + } +} diff --git a/src/zutil/net/update/UpdateConfigMessage.java b/src/zutil/net/update/UpdateConfigMessage.java new file mode 100644 index 00000000..86737b53 --- /dev/null +++ b/src/zutil/net/update/UpdateConfigMessage.java @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import java.io.Serializable; + +/** + * A class that contains configuration information + * + * @author Ziver + */ +class UpdateConfigMessage implements Serializable{ + private static final long serialVersionUID = 1L; + + protected String hashAlgorithm; + protected boolean compression; +} diff --git a/src/zutil/net/update/UpdateServer.java b/src/zutil/net/update/UpdateServer.java new file mode 100644 index 00000000..2d6f7fc2 --- /dev/null +++ b/src/zutil/net/update/UpdateServer.java @@ -0,0 +1,125 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import zutil.io.MultiPrintStream; +import zutil.log.LogUtil; +import zutil.net.threaded.ThreadedTCPNetworkServer; +import zutil.net.threaded.ThreadedTCPNetworkServerThread; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class UpdateServer extends ThreadedTCPNetworkServer{ + private static final Logger logger = LogUtil.getLogger(); + + private FileListMessage fileList; + + /** + * Creates a UpdateServer Thread + * + * @param path The path to sync the clients with + */ + public UpdateServer(int port, String path) throws Exception{ + super(port); + fileList = new FileListMessage(path); + MultiPrintStream.out.dump(fileList); + + this.start(); + logger.info("Update Server Ready."); + } + + @Override + protected ThreadedTCPNetworkServerThread getThreadInstance(Socket s) { + return new UpdateServerThread(s); + } + + /** + * Handles all the connecting clients + * + * @author Ziver + */ + class UpdateServerThread implements ThreadedTCPNetworkServerThread{ + private ObjectOutputStream out; + private ObjectInputStream in; + private Socket socket; + + /** + * Creates a UpdateServerThread + * + * @param client is the socket to the client + */ + public UpdateServerThread(Socket c){ + socket = c; + try { + out = new ObjectOutputStream( socket.getOutputStream()); + in = new ObjectInputStream ( socket.getInputStream() ); + } catch (IOException e) { + logger.log(Level.SEVERE, null, e); + } + + } + + public void run(){ + try { + logger.info("Client["+socket.getInetAddress()+"] connectiong..."); + // receive the clients file list + FileListMessage clientFileList = (FileListMessage)in.readObject(); + MultiPrintStream.out.dump(clientFileList); + FileListMessage diff = fileList.getDiff( clientFileList ); + MultiPrintStream.out.dump(diff); + out.writeObject( diff ); + + logger.info("Updating client["+socket.getInetAddress()+"]..."); + for(FileInfo info : diff.getFileList()){ + // send file data + FileInputStream input = new FileInputStream( info.getFile() ); + byte[] nextBytes = new byte[ socket.getSendBufferSize() ]; + int bytesRead = 0; + while((bytesRead = input.read(nextBytes)) > 0){ + out.write(nextBytes,0,bytesRead); + } + out.flush(); + input.close(); + } + + out.flush(); + socket.close(); + logger.info("Client["+socket.getInetAddress()+"] update done."); + } catch (Exception e) { + logger.log(Level.SEVERE, "Update error Client["+socket.getInetAddress()+"].", e); + } finally { + logger.info("Client["+socket.getInetAddress()+"] disconnected."); + } + } + } +} + + diff --git a/src/zutil/net/update/Zupdater.java b/src/zutil/net/update/Zupdater.java new file mode 100644 index 00000000..574dc6fe --- /dev/null +++ b/src/zutil/net/update/Zupdater.java @@ -0,0 +1,147 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import zutil.ProgressListener; +import zutil.StringUtil; + +import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.border.EmptyBorder; +import java.awt.Dialog.ModalExclusionType; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +public class Zupdater extends JFrame implements ProgressListener{ + private static final long serialVersionUID = 1L; + + private JPanel contentPane; + private JLabel lblSpeed; + private JLabel lblFile; + private JProgressBar progressBar; + + /** + * Launch the application. + */ + public static void main(String[] args) { + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + Zupdater frame = new Zupdater(); + frame.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + + public void progressUpdate(UpdateClient source, FileInfo info, double percent) { + lblFile.setText( info.getPath() ); + progressBar.setValue( (int)percent ); + progressBar.setString( StringUtil.formatByteSizeToString(source.getTotalReceived()) + + " / "+StringUtil.formatByteSizeToString(source.getTotalSize())); + + lblSpeed.setText( StringUtil.formatByteSizeToString(((UpdateClient) source).getSpeed())+"/s" ); + } + + + /** + * Create the frame. + */ + public Zupdater() { + setModalExclusionType(ModalExclusionType.APPLICATION_EXCLUDE); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setAlwaysOnTop(true); + setResizable(false); + setTitle("Updating..."); + setBounds(100, 100, 537, 124); + contentPane = new JPanel(); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + + progressBar = new JProgressBar(); + progressBar.setString("2.5 MB / 5 MB"); + progressBar.setValue(50); + progressBar.setStringPainted(true); + progressBar.setToolTipText(""); + + lblFile = new JLabel("apa.zip"); + + lblSpeed = new JLabel("200 kb/s"); + lblSpeed.setHorizontalAlignment(SwingConstants.RIGHT); + + JSeparator separator = new JSeparator(); + + JButton btnCancel = new JButton("Cancel"); + btnCancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + + JLabel lblFile_1 = new JLabel("File:"); + GroupLayout gl_contentPane = new GroupLayout(contentPane); + gl_contentPane.setHorizontalGroup( + gl_contentPane.createParallelGroup(Alignment.TRAILING) + .addGroup(gl_contentPane.createSequentialGroup() + .addGap(10) + .addComponent(progressBar, GroupLayout.DEFAULT_SIZE, 501, Short.MAX_VALUE) + .addGap(10)) + .addComponent(separator, GroupLayout.DEFAULT_SIZE, 521, Short.MAX_VALUE) + .addGroup(gl_contentPane.createSequentialGroup() + .addContainerGap() + .addComponent(lblFile_1) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(lblFile, GroupLayout.PREFERRED_SIZE, 331, GroupLayout.PREFERRED_SIZE) + .addGap(60) + .addComponent(lblSpeed, GroupLayout.DEFAULT_SIZE, 84, Short.MAX_VALUE) + .addContainerGap()) + .addGroup(gl_contentPane.createSequentialGroup() + .addContainerGap() + .addComponent(btnCancel)) + ); + gl_contentPane.setVerticalGroup( + gl_contentPane.createParallelGroup(Alignment.LEADING) + .addGroup(gl_contentPane.createSequentialGroup() + .addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE) + .addComponent(lblSpeed) + .addComponent(lblFile) + .addComponent(lblFile_1)) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(progressBar, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(separator, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(btnCancel) + .addContainerGap(14, Short.MAX_VALUE)) + ); + contentPane.setLayout(gl_contentPane); + } +} diff --git a/src/zutil/net/upnp/UPnPMediaServer.java b/src/zutil/net/upnp/UPnPMediaServer.java new file mode 100755 index 00000000..02be4480 --- /dev/null +++ b/src/zutil/net/upnp/UPnPMediaServer.java @@ -0,0 +1,117 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.upnp; + +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpPrintStream; + +import java.io.IOException; +import java.util.Map; +import java.util.UUID; + +/** + * This class is a UPnP AV Media Server that handles all the + * other UPnP services + * + * @author Ziver + */ +public class UPnPMediaServer extends UPnPRootDevice{ + public static final String RELATIVE_URL = "upnp/rootdev"; + + private String url; + private String uuid; + + public UPnPMediaServer(String location){ + url = location; + } + + public void respond(HttpPrintStream out, + HttpHeader headers, + Map session, + Map cookie, + Map request) throws IOException { + + out.enableBuffering(true); + out.setHeader("Content-Type", "text/xml"); + + out.println(""); + out.println(""); + out.println(" "); + out.println(" 1"); + out.println(" 0"); + out.println(" "); + out.println(" "+url+"");//"+ssdp.getLocation()+" + out.println(" "); + out.println(" urn:schemas-upnp-org:device:MediaServer:1"); + out.println(" ZupNP AV Media Server"); + out.println(" Ziver Koc"); + out.println(" http://ziver.koc.se"); + out.println(""); + out.println(" ZupNP Server"); + out.println(" UPnP AV Media Server"); + out.println(" 0.1"); + out.println(" "+getUUID()+""); + out.println(" "); + out.println(" "); + out.println(" urn:schemas-upnp-org:service:ConnectionManager:1"); + out.println(" urn:upnp-org:serviceId:CMGR_1-0"); + out.println(" CMGR_Control/GetServDesc"); + out.println(" CMGR_Control"); + out.println(" CMGR_Event"); + out.println(" "); + out.println(" "); + out.println(" urn:schemas-upnp-org:service:ContentDirectory:1"); + out.println(" urn:upnp-org:serviceId:CDS_1-0"); + out.println(" SCP/ContentDir"); + out.println(" Action/ContentDir"); + out.println(" Event/ContentDir"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(""); + out.flush(); + } + + + public long getExpirationTime() { + return 60*30; // 30min + } + public String getLocation() { + return url+"RootDesc"; + } + public String getSearchTarget() { + return "upnp:rootdevice"; + } + public String getUSN() { + return getUUID()+"::upnp:rootdevice"; + } + public String getUUID() { + if(uuid==null){ + uuid = "uuid:"+UUID.nameUUIDFromBytes( this.getClass().toString().getBytes() ); //(url+Math.random()).getBytes() + } + return uuid; + } + +} diff --git a/src/zutil/net/upnp/UPnPRootDevice.java b/src/zutil/net/upnp/UPnPRootDevice.java new file mode 100644 index 00000000..83f43ac2 --- /dev/null +++ b/src/zutil/net/upnp/UPnPRootDevice.java @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.upnp; + +import zutil.net.http.HttpPage; +import zutil.net.ssdp.SSDPServiceInfo; +/** + * This class is a UPnP Server class that will be extended + * by all root devices handles all the other UPnP services + * + * @author Ziver + */ +public abstract class UPnPRootDevice implements HttpPage, SSDPServiceInfo{ + +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraController.java b/src/zutil/net/upnp/UPnPService.java similarity index 85% rename from plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraController.java rename to src/zutil/net/upnp/UPnPService.java index 687feced..15866201 100644 --- a/plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraController.java +++ b/src/zutil/net/upnp/UPnPService.java @@ -1,32 +1,34 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.nvr.intf; - -import se.hal.intf.HalAbstractController; - - -public interface HalCameraController extends HalAbstractController { - -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.upnp; + +/** + * Information about a UPNP Service + * + * @author Ziver + */ +public interface UPnPService { + +} diff --git a/src/zutil/net/upnp/service/BrowseRetObj.java b/src/zutil/net/upnp/service/BrowseRetObj.java new file mode 100755 index 00000000..e87a022f --- /dev/null +++ b/src/zutil/net/upnp/service/BrowseRetObj.java @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.upnp.service; + +import zutil.net.ws.WSReturnObject; + + +public class BrowseRetObj extends WSReturnObject{ + @WSValueName("Result") + public String Result; + @WSValueName("NumberReturned") + public int NumberReturned; + @WSValueName("TotalMatches") + public int TotalMatches; + @WSValueName("UpdateID") + public int UpdateID; + } diff --git a/src/zutil/net/upnp/service/UPnPContentDirectory.java b/src/zutil/net/upnp/service/UPnPContentDirectory.java new file mode 100755 index 00000000..12141981 --- /dev/null +++ b/src/zutil/net/upnp/service/UPnPContentDirectory.java @@ -0,0 +1,616 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.upnp.service; + +import org.dom4j.DocumentException; +import zutil.io.file.FileUtil; +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpPage; +import zutil.net.http.HttpPrintStream; +import zutil.net.upnp.UPnPService; +import zutil.net.ws.WSInterface; +import zutil.net.ws.WSReturnObject; + +import java.io.File; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * Information about a UPNP Service + * + * @author Ziver + */ +public class UPnPContentDirectory implements UPnPService, HttpPage, WSInterface { + public static final int VERSION = 1; + + private static List file_list; + + public UPnPContentDirectory(){} + + public UPnPContentDirectory(File dir){ + file_list = FileUtil.search(dir, new LinkedList(), true, Integer.MAX_VALUE); + } + + /** + * This action returns the searching capabilities + * that are supported by the device. + * + */ + @WSReturnName("SortCaps") + public String GetSearchCapabilities(){ + // "dc:title,res@size" + return ""; + } + + /** + * Returns the CSV list of meta-data tags that can + * be used in sortCriteria + * + */ + @WSReturnName("SortCaps") + public String GetSortCapabilities(){ + return "dc:title"; + } + + /** + * This action returns the current value of state variable + * SystemUpdateID. It can be used by clients that want to + * 'poll' for any changes in the Content Directory + * (as opposed to subscribing to events). + * + */ + @WSReturnName("Id") + public int GetSystemUpdateID(){ + return 0; + } + + /** + * This action allows the caller to incrementally browse + * the native hierarchy of the Content Directory objects + * exposed by the Content Directory Service, including + * information listing the classes of objects available + * in any particular object container. + * @throws DocumentException + * + */ + //@WSNameSpace("urn:schemas-upnp-org:service:ContentDirectory:1") + public BrowseRetObj Browse( + @WSParamName("ObjectID") String ObjectID, + @WSParamName("BrowseFlag") String BrowseFlag, + @WSParamName("Filter") String Filter, + @WSParamName("StartingIndex") int StartingIndex, + @WSParamName("RequestedCount") int RequestedCount, + @WSParamName("SortCriteria") String SortCriteria) throws DocumentException{ + + BrowseRetObj ret = new BrowseRetObj(); + if( BrowseFlag.equals("BrowseMetadata") ){ + + } + else if( BrowseFlag.equals("BrowseDirectChildren") ){ + StringBuffer xml = new StringBuffer(); + xml.append( "" ); + List tmp = FileUtil.search( file_list.get(Integer.parseInt(ObjectID)), new LinkedList(), false ); + for(File file : tmp){ + xml.append(" "); + + xml.append(" "+file.getName()+" "); + if( file.isDirectory() ) + xml.append(" object.container.storageFolder "); + else + xml.append(" object.container "); + xml.append(" "+(int)(file.length()/1000)+" "); + xml.append(" "); + + ret.NumberReturned++; + ret.TotalMatches++; + } + xml.append( "" ); + + ret.Result = xml.toString(); + //Document document = DocumentHelper.parseText( xml.toString() ); + //ret.Result = document.getRootElement(); + } + return ret; + } + public class BrowseRetObj extends WSReturnObject{ + @WSValueName("Result") + public String Result; + @WSValueName("NumberReturned") + public int NumberReturned; + @WSValueName("TotalMatches") + public int TotalMatches; + @WSValueName("UpdateID") + public int UpdateID; + } + + + @WSDisabled + public void respond(HttpPrintStream out, HttpHeader headers, + Map session, + Map cookie, + Map request) throws IOException { + + out.enableBuffering(true); + out.setHeader("Content-Type", "text/xml"); + + out.println(""); + out.println(""); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" TransferIDs"); + out.println(" yes"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_Result"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_SearchCriteria"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_BrowseFlag"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" BrowseMetadata"); + out.println(" BrowseDirectChildren"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_Filter"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_SortCriteria"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_Index"); + out.println(" no"); + out.println(" ui4"); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_Count"); + out.println(" no"); + out.println(" ui4"); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_UpdateID"); + out.println(" no"); + out.println(" ui4"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_TransferID"); + out.println(" no"); + out.println(" ui4"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_TransferStatus"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" COMPLETED"); + out.println(" ERROR"); + out.println(" IN_PROGRESS"); + out.println(" STOPPED"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_TransferLength"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_TransferTotal"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_TagValueList"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" A_ARG_TYPE_URI"); + out.println(" no"); + out.println(" uri"); + out.println(" "); + out.println(" "); + out.println(" SearchCapabilities"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" SortCapabilities"); + out.println(" no"); + out.println(" string"); + out.println(" "); + out.println(" "); + out.println(" SystemUpdateID"); + out.println(" yes"); + out.println(" ui4"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" ContainerUpdateIDs"); + out.println(" yes"); + out.println(" string"); + out.println(" "); + out.println(" "); + + + out.println(" "); + out.println(" "); + out.println(" GetSearchCapabilities"); + out.println(" "); + out.println(" "); + out.println(" SearchCaps"); + out.println(" out"); + out.println(" SearchCapabilities"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" GetSortCapabilities"); + out.println(" "); + out.println(" "); + out.println(" SortCaps"); + out.println(" out"); + out.println(" SortCapabilities"); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" GetSystemUpdateID"); + out.println(" "); + out.println(" "); + out.println(" Id"); + out.println(" out"); + out.println(" SystemUpdateID"); + out.println(" "); + out.println(" "); + out.println(" "); + + out.println(" "); + out.println(" Browse"); + out.println(" "); + out.println(" "); + out.println(" ObjectID"); + out.println(" in"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" BrowseFlag"); + out.println(" in"); + out.println(" A_ARG_TYPE_BrowseFlag"); + out.println(" "); + out.println(" "); + out.println(" Filter"); + out.println(" in"); + out.println(" A_ARG_TYPE_Filter"); + out.println(" "); + out.println(" "); + out.println(" StartingIndex"); + out.println(" in"); + out.println(" A_ARG_TYPE_Index"); + out.println(" "); + out.println(" "); + out.println(" RequestedCount"); + out.println(" in"); + out.println(" A_ARG_TYPE_Count"); + out.println(" "); + out.println(" "); + out.println(" SortCriteria"); + out.println(" in"); + out.println(" A_ARG_TYPE_SortCriteria"); + out.println(" "); + out.println(" "); + out.println(" Result"); + out.println(" out"); + out.println(" A_ARG_TYPE_Result"); + out.println(" "); + out.println(" "); + out.println(" NumberReturned"); + out.println(" out"); + out.println(" A_ARG_TYPE_Count"); + out.println(" "); + out.println(" "); + out.println(" TotalMatches"); + out.println(" out"); + out.println(" A_ARG_TYPE_Count"); + out.println(" "); + out.println(" "); + out.println(" UpdateID"); + out.println(" out"); + out.println(" A_ARG_TYPE_UpdateID"); + out.println(" "); + out.println(" "); + out.println(" "); + + /*out.println(" "); + out.println(" "); + out.println(" Search"); + out.println(" "); + out.println(" "); + out.println(" ContainerID"); + out.println(" in"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" SearchCriteria"); + out.println(" in"); + out.println(" A_ARG_TYPE_SearchCriteria "); + out.println(" "); + out.println(" "); + out.println(" Filter"); + out.println(" in"); + out.println(" A_ARG_TYPE_Filter"); + out.println(" "); + out.println(" "); + out.println(" StartingIndex"); + out.println(" in"); + out.println(" A_ARG_TYPE_Index"); + out.println(" "); + out.println(" "); + out.println(" RequestedCount"); + out.println(" in"); + out.println(" A_ARG_TYPE_Count"); + out.println(" "); + out.println(" "); + out.println(" SortCriteria"); + out.println(" in"); + out.println(" A_ARG_TYPE_SortCriteria"); + out.println(" "); + out.println(" "); + out.println(" Result"); + out.println(" out"); + out.println(" A_ARG_TYPE_Result"); + out.println(" "); + out.println(" "); + out.println(" NumberReturned"); + out.println(" out"); + out.println(" A_ARG_TYPE_Count"); + out.println(" "); + out.println(" "); + out.println(" TotalMatches"); + out.println(" out"); + out.println(" A_ARG_TYPE_Count"); + out.println(" "); + out.println(" "); + out.println(" UpdateID"); + out.println(" out"); + out.println(" A_ARG_TYPE_UpdateID"); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" CreateObject"); + out.println(" "); + out.println(" "); + out.println(" ContainerID"); + out.println(" in"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" Elements"); + out.println(" in"); + out.println(" A_ARG_TYPE_Result"); + out.println(" "); + out.println(" "); + out.println(" ObjectID"); + out.println(" out"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" Result"); + out.println(" out"); + out.println(" A_ARG_TYPE_Result"); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" DestroyObject"); + out.println(" "); + out.println(" "); + out.println(" ObjectID"); + out.println(" in"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" UpdateObject"); + out.println(" "); + out.println(" "); + out.println(" ObjectID"); + out.println(" in"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" CurrentTagValue"); + out.println(" in"); + out.println(" A_ARG_TYPE_TagValueList "); + out.println(" "); + out.println(" "); + out.println(" NewTagValue"); + out.println(" in"); + out.println(" A_ARG_TYPE_TagValueList "); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" ImportResource"); + out.println(" "); + out.println(" "); + out.println(" SourceURI"); + out.println(" in"); + out.println(" A_ARG_TYPE_URI"); + out.println(" "); + out.println(" "); + out.println(" DestinationURI"); + out.println(" in"); + out.println(" A_ARG_TYPE_URI"); + out.println(" "); + out.println(" "); + out.println(" TransferID"); + out.println(" out"); + out.println(" A_ARG_TYPE_TransferID "); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" ExportResource"); + out.println(" "); + out.println(" "); + out.println(" SourceURI"); + out.println(" in"); + out.println(" A_ARG_TYPE_URI"); + out.println(" "); + out.println(" "); + out.println(" DestinationURI"); + out.println(" in"); + out.println(" A_ARG_TYPE_URI"); + out.println(" "); + out.println(" "); + out.println(" TransferID"); + out.println(" out"); + out.println(" A_ARG_TYPE_TransferID "); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" StopTransferResource"); + out.println(" "); + out.println(" "); + out.println(" TransferID"); + out.println(" in"); + out.println(" A_ARG_TYPE_TransferID "); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" GetTransferProgress"); + out.println(" "); + out.println(" "); + out.println(" TransferID"); + out.println(" in"); + out.println(" A_ARG_TYPE_TransferID "); + out.println(" "); + out.println(" "); + out.println(" TransferStatus"); + out.println(" out"); + out.println(" A_ARG_TYPE_TransferStatus "); + out.println(" "); + out.println(" "); + out.println(" TransferLength"); + out.println(" out"); + out.println(" A_ARG_TYPE_TransferLength "); + out.println(" "); + out.println(" "); + out.println(" TransferTotal"); + out.println(" out"); + out.println(" A_ARG_TYPE_TransferTotal"); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" DeleteResource"); + out.println(" "); + out.println(" "); + out.println(" ResourceURI"); + out.println(" in"); + out.println(" A_ARG_TYPE_URI"); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + /*out.println(" "); + out.println(" "); + out.println(" CreateReference"); + out.println(" "); + out.println(" "); + out.println(" ContainerID"); + out.println(" in"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" ObjectID"); + out.println(" in"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" NewID"); + out.println(" out"); + out.println(" A_ARG_TYPE_ObjectID"); + out.println(" "); + out.println(" "); + out.println(" ");*/ + + out.println(" "); + out.println(""); + } +} diff --git a/src/zutil/net/ws/WSClientFactory.java b/src/zutil/net/ws/WSClientFactory.java new file mode 100755 index 00000000..0b90a0ba --- /dev/null +++ b/src/zutil/net/ws/WSClientFactory.java @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws; + +import zutil.log.LogUtil; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This is an factory that generates clients for an unspecified web services + * + * @author Ziver + */ +public class WSClientFactory { + private static Logger logger = LogUtil.getLogger(); + + /** + * Generates a Client Object for the web service. + * + * @param is the class of the web service definition + * @param intf is the class of the web service definition + * @return a client Object + */ + public static T createClient(Class intf, InvocationHandler handler){ + if( !WSInterface.class.isAssignableFrom( intf )){ + throw new ClassCastException("The Web Service class is not a subclass of WSInterface!"); + } + + try { + Class proxyClass = Proxy.getProxyClass( + WSClientFactory.class.getClassLoader(), + new Class[]{intf}); + Constructor constructor = proxyClass.getConstructor( + new Class[]{InvocationHandler.class}); + T obj = constructor.newInstance( + new Object[]{handler}); + + return obj; + } catch (Exception e){ + logger.log(Level.SEVERE, null, e); + } + + return null; + } + +} diff --git a/src/zutil/net/ws/WSInterface.java b/src/zutil/net/ws/WSInterface.java new file mode 100644 index 00000000..7257a610 --- /dev/null +++ b/src/zutil/net/ws/WSInterface.java @@ -0,0 +1,139 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +/** + * + * Specifies web service parameter names and other things. + * Example: + *
    + *	private static class Test implements WSInterface{
    + *		public Test(){}
    + *	
    + *		@WSDocumentation("blabla")
    + *		@WSDLParamDocumentation("olle = an variable?")
    + *		public void pubZ( 
    + *				@WSParamName("olle") int lol) 
    + *				throws Exception{ 
    + *			....
    + *		}
    + *	
    + *		@WSReturnName("param")
    + *		public String pubA( 
    + *				@WSParamName(value="lol", optional=true) String lol) 
    + *				throws Exception{ 
    + *			....
    + *		}
    + *	
    + *		@WSDisabled()
    + *		public void privaZ(....){ 
    + *			...
    + *		}		
    + *	}
    + * 
    + * 
    + * @author Ziver + */ +public interface WSInterface { + /** + * Annotation that assigns a name to an parameters + * in an method. + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + public @interface WSParamName { + String value(); + boolean optional() default false; + } + + /** + * Annotation that assigns a name to the return value + * in an method. + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface WSReturnName { + String value(); + } + + /** + * Disables publication of the given method + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface WSDisabled { } + + /** + * Method or Parameter comments for the WSDL. + * These comments are put in the message part of the WSDL + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface WSDocumentation{ + String value(); + } + + /** + * Parameter comments for the WSDL. + * These comments are put in the message part of the WSDL + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface WSParamDocumentation{ + String value(); + } + + /** + * This method will be used in the header. + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface WSHeader { } + + /** + * Specifies the name space for method. + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + //@Target(ElementType.TYPE) + public @interface WSNamespace { + String value(); + } +} diff --git a/src/zutil/net/ws/WSMethodDef.java b/src/zutil/net/ws/WSMethodDef.java new file mode 100644 index 00000000..080c7aa9 --- /dev/null +++ b/src/zutil/net/ws/WSMethodDef.java @@ -0,0 +1,270 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws; + +import zutil.net.ws.WSInterface.WSDocumentation; +import zutil.net.ws.WSInterface.WSNamespace; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +/** + * This is a web service method definition class + * + * @author Ziver + */ +// TODO: Header parameters +public class WSMethodDef { + /** The parent web service definition **/ + private WebServiceDef wsDef; + /** A list of input parameters **/ + private ArrayList inputs; + /** A List of return parameters of the method **/ + private ArrayList outputs; + /** A List of exceptions that this method throws **/ + private ArrayList> exceptions; + /** The real method that this class represent, can be null if its a remote method **/ + private Method method; + /** Documentation of the method **/ + private String doc; + /** This is the namespace of the method **/ + private String namespace; + /** The published name of the method **/ + private String name; + + + /** + * + * @param me is a method in a class that implements WSInterface + */ + protected WSMethodDef( WebServiceDef wsDef, Method me) { + if( !WSInterface.class.isAssignableFrom(me.getDeclaringClass()) ) + throw new ClassCastException("Declaring class does not implement WSInterface!"); + this.wsDef = wsDef; + method = me; + inputs = new ArrayList(); + outputs = new ArrayList(); + exceptions = new ArrayList>(); + name = method.getName(); + + //***** Documentation & Namespace + WSDocumentation tmpDoc = method.getAnnotation( WSDocumentation.class ); + if(tmpDoc != null){ + doc = tmpDoc.value(); + } + WSNamespace tmpSpace = method.getAnnotation( WSNamespace.class ); + if( tmpSpace != null ) + namespace = tmpSpace.value(); + else + namespace = wsDef.getNamespace()+"?#"+name; + + //***** Exceptions + for( Class exc : method.getExceptionTypes() ){ + exceptions.add( exc ); + } + + //********* Get the input parameter names ********** + Annotation[][] paramAnnotation = method.getParameterAnnotations(); + Class[] inputTypes = method.getParameterTypes(); + + for(int i=0; i retClass = method.getReturnType(); + Field[] fields = retClass.getFields(); + + for(int i=0; i> getExceptions(){ + return exceptions; + } + + /** + * @return the number of parameters for this method + */ + public int getInputCount(){ + return inputs.size(); + } + + /** + * @return a list of input parameters + */ + public List getInputs(){ + return inputs; + } + + /** + * @param index is a index + * @return a {@link WSParameterDef} object in the given index + */ + public WSParameterDef getInput( int index ){ + return inputs.get( index ); + } + + /** + * @return the number of parameters for this method + */ + public int getOutputCount(){ + return outputs.size(); + } + + /** + * @return a list of input parameters + */ + public List getOutputs(){ + return outputs; + } + + /** + * @param index is a index + * @return a {@link WSParameterDef} object in the given index + */ + public WSParameterDef getOutput( int index ){ + return outputs.get( index ); + } + + /** + * @return Documentation of the method if one exists or else null + */ + public String getDocumentation(){ + return doc; + } + + /** + * @return the namespace of the method + */ + public String getNamespace(){ + return namespace; + } + + public WebServiceDef getWebService(){ + return wsDef; + } + + /** + * Invokes a specified method + * + * @param obj the object the method will called on + * @param params a vector with arguments + */ + public Object invoke(Object obj, Object[] params) throws Throwable{ + try { + return this.method.invoke(obj, params ); + } catch (IllegalArgumentException e) { + throw e; + } catch (IllegalAccessException e) { + throw e; + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } + + + public String toString(){ + StringBuilder tmp = new StringBuilder(); + boolean first = true; + tmp.append(name).append("("); + for(WSParameterDef param : inputs){ + if(first) + first = false; + else + tmp.append(" ,"); + tmp.append(param.getParamClass().getSimpleName()); + tmp.append(" "); + tmp.append(param.getName()); + } + tmp.append(") => "); + first = true; + for(WSParameterDef param : outputs){ + if(first) + first = false; + else + tmp.append(" ,"); + tmp.append(param.getParamClass().getSimpleName()); + tmp.append(" "); + tmp.append(param.getName()); + } + return tmp.toString(); + } +} diff --git a/src/zutil/net/ws/WSParameterDef.java b/src/zutil/net/ws/WSParameterDef.java new file mode 100644 index 00000000..6557b84f --- /dev/null +++ b/src/zutil/net/ws/WSParameterDef.java @@ -0,0 +1,83 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws; + +/** + * This is a web service parameter definition class + * + * @author Ziver + */ +public class WSParameterDef{ + /** The parent method **/ + private WSMethodDef mDef; + /** The class type of the parameter **/ + private Class paramClass; + /** The web service name of the parameter **/ + private String name; + /** Developer documentation **/ + private String doc; + /** If this parameter is optional **/ + private boolean optional; + /** Is it an header parameter **/ + //boolean header; + + protected WSParameterDef( WSMethodDef mDef ){ + this.mDef = mDef; + this.optional = false; + } + + + public Class getParamClass() { + return paramClass; + } + protected void setParamClass(Class paramClass) { + this.paramClass = paramClass; + } + + public String getName() { + return name; + } + protected void setName(String name) { + this.name = name; + } + + public String getDoc() { + return doc; + } + protected void setDoc(String doc) { + this.doc = doc; + } + + public boolean isOptional() { + return optional; + } + protected void setOptional(boolean optional) { + this.optional = optional; + } + + public WSMethodDef getMethod(){ + return mDef; + } +} diff --git a/src/zutil/net/ws/WSReturnObject.java b/src/zutil/net/ws/WSReturnObject.java new file mode 100644 index 00000000..de379389 --- /dev/null +++ b/src/zutil/net/ws/WSReturnObject.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; + +/** + * This class is used as an return Object for a web service. + * If an class implements this interface then it can return + * multiple values through the WSInterface. And the + * implementing class will be transparent. Example: + * + *
    + * 	private static class TestObject implements WSReturnObject{
    + *		@WSValueName("name")
    + *		public String name;
    + *		@WSValueName("lastname")
    + *		public String lastname;
    + *
    + *		public TestObject(String n, String l){
    + *			name = n;
    + *			lastname = l;
    + *		}
    + *	}
    + * 
    + * + * @author Ziver + * + */ +public class WSReturnObject{ + /** + * Method comments for the WSDL. + * These comments are put in the operation part of the WSDL + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface WSDLDocumentation{ + String value(); + } + + /** + * Annotation that assigns a name to the return value + * to the field. + * + * @author Ziver + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface WSValueName { + String value(); + boolean optional() default false; + } + + + public Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException{ + return field.get(this); + } +} diff --git a/src/zutil/net/ws/WebServiceDef.java b/src/zutil/net/ws/WebServiceDef.java new file mode 100644 index 00000000..f56c574f --- /dev/null +++ b/src/zutil/net/ws/WebServiceDef.java @@ -0,0 +1,121 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.HashMap; +import java.util.Set; + +/** + * Defines a web service from a class implementing the {@link zutil.net.ws.WSInterface} + * + * @author Ziver + */ +public class WebServiceDef { + /** A map of methods in this Service **/ + private HashMap methods; + /** Namespace of the service **/ + private String namespace; + /** Name of the web service **/ + private String name; + /** This is the WSInterface class **/ + private Class intf; + + + public WebServiceDef(Class intf){ + this.intf = intf; + methods = new HashMap(); + name = intf.getSimpleName(); + + if( intf.getAnnotation( WSInterface.WSNamespace.class ) != null ) + this.namespace = intf.getAnnotation( WSInterface.WSNamespace.class ).value(); + + for(Method m : intf.getDeclaredMethods()){ + // check for public methods + if((m.getModifiers() & Modifier.PUBLIC) > 0 && + !m.isAnnotationPresent(WSInterface.WSDisabled.class)){ + WSMethodDef method = new WSMethodDef(this, m); + methods.put(method.getName(), method); + } + } + } + + /** + * @return the class that defines this web service + */ + public Class getWSClass(){ + return intf; + } + + /** + * @return the name of the Service (usually the class name of the WSInterface) + */ + public String getName(){ + return name; + } + + /** + * @param name is the name of the method + * @return if there is a method by the given name + */ + public boolean hasMethod( String name ){ + return methods.containsKey( name ); + } + + /** + * @param name is the name of the method + * @return the method or null if there is no such method + */ + public WSMethodDef getMethod( String name ){ + return methods.get( name ); + } + + /** + * @return a Set of all the method names + */ + public Set getMethodNames(){ + return methods.keySet(); + } + + /** + * @return all the methods + */ + public Collection getMethods(){ + return methods.values(); + } + + /** + * @return the namespace of this web service ( usually the URL of the service ) + */ + public String getNamespace(){ + return namespace; + } + + public WSInterface newInstance() throws InstantiationException, IllegalAccessException { + return intf.newInstance(); + } +} diff --git a/src/zutil/net/ws/rest/RestHttpPage.java b/src/zutil/net/ws/rest/RestHttpPage.java new file mode 100755 index 00000000..33dbbb40 --- /dev/null +++ b/src/zutil/net/ws/rest/RestHttpPage.java @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws.rest; + +import zutil.converter.Converter; +import zutil.io.StringOutputStream; +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpPage; +import zutil.net.http.HttpPrintStream; +import zutil.net.ws.WSInterface; +import zutil.net.ws.WSMethodDef; +import zutil.net.ws.WSParameterDef; +import zutil.net.ws.WebServiceDef; +import zutil.parser.json.JSONObjectOutputStream; + +import java.io.IOException; +import java.util.Map; + +/** + * User: Ziver + */ +public class RestHttpPage implements HttpPage { + + /** The object that the functions will be invoked from **/ + private WebServiceDef wsDef; + /** This instance of the web service class is used if session is disabled **/ + private WSInterface ws; + + + public RestHttpPage( WSInterface wsObject ){ + this.ws = wsObject; + this.wsDef = new WebServiceDef(ws.getClass()); + } + + + @Override + public void respond(HttpPrintStream out, + HttpHeader headers, + Map session, + Map cookie, + Map request) throws IOException { + try { + out.println( + execute(headers.getRequestURL(), request)); + } catch (Throwable throwable) { + throw new IOException(throwable); + } + } + + + private String execute(String targetMethod, Map input) throws Throwable { + if( wsDef.hasMethod(targetMethod) ){ + // Parse request + WSMethodDef m = wsDef.getMethod(targetMethod); + Object[] params = prepareInputParams(m, input); + + // Invoke + Object ret = m.invoke(ws, params); + + // Generate Response + StringOutputStream dummyOut = new StringOutputStream(); + JSONObjectOutputStream out = new JSONObjectOutputStream(dummyOut); + out.writeObject(ret); + out.close(); + return dummyOut.toString(); + } + return "{error: \"Unknown target: "+targetMethod+"\"}"; + } + + private Object[] prepareInputParams(WSMethodDef method, Map input){ + Object[] inputParams = new Object[method.getInputCount()]; + + // Get the parameter values + for(int i=0; i is the class of the web service definition + * @param url is the target service url + * @param intf is the class of the web service definition + * @return a client Object + */ + @SuppressWarnings("unchecked") + public static T createClient(URL url, Class intf){ + return createClient(url, intf, + new WebServiceDef((Class)intf) ); + } + + /** + * Generates a Client Object for the web service. + * + * @param is the class of the web service definition + * @param url is the target service url + * @param intf is the class of the web service definition + * @param wsDef is the web service definition of the intf parameter + * @return a client Object + */ + public static T createClient(URL url, Class intf, WebServiceDef wsDef){ + T obj = WSClientFactory.createClient( intf, + new SOAPClientInvocationHandler(url, wsDef)); + return obj; + } + +} diff --git a/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java b/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java new file mode 100755 index 00000000..b4272320 --- /dev/null +++ b/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java @@ -0,0 +1,130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws.soap; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import zutil.io.IOUtil; +import zutil.log.LogUtil; +import zutil.net.http.HttpClient; +import zutil.net.http.HttpHeaderParser; +import zutil.net.ws.WSInterface; +import zutil.net.ws.WSMethodDef; +import zutil.net.ws.WSParameterDef; +import zutil.net.ws.WebServiceDef; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This is an abstract client that will do generic requests to a + * SOAP Web service + * + * @author Ziver + */ +public class SOAPClientInvocationHandler implements InvocationHandler { + private static Logger logger = LogUtil.getLogger(); + + private WebServiceDef wsDef; + /** Web address of the web service */ + protected URL url; + + + public SOAPClientInvocationHandler(URL url, WebServiceDef wsDef){ + this.url = url; + this.wsDef = wsDef; + } + + + /** + * Makes a request to the target web service + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // Generate XML + Document document = genSOAPRequest((WSInterface)proxy, method.getName(), args); + String reqXml = document.asXML(); + + + // Send request + HttpClient request = new HttpClient(HttpClient.HttpRequestType.POST); + request.setURL(url); + request.setData(reqXml); + HttpHeaderParser response = request.send(); + String rspXml = IOUtil.getContentAsString( request.getResponseReader()); + + // DEBUG + if( logger.isLoggable(Level.FINEST) ){ + System.out.println("********** Request"); + System.out.println(reqXml); + System.out.println("********** Response"); + System.out.println(rspXml); + } + + return parseSOAPResponse(rspXml); + } + + + private Document genSOAPRequest(WSInterface obj, String targetMethod, Object[] args){ + logger.fine("Sending request for "+targetMethod); + Document document = DocumentHelper.createDocument(); + Element envelope = document.addElement("soap:Envelope"); + WSMethodDef methodDef = wsDef.getMethod( targetMethod ); + try { + envelope.addNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"); + envelope.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + envelope.addNamespace("xsd", "http://www.w3.org/2001/XMLSchema"); + + Element body = envelope.addElement( "soap:Body" ); + Element method = body.addElement(""); + method.addNamespace("m", methodDef.getNamespace() ); + method.setName("m:"+methodDef.getName()+"Request"); + for(int i=0; i-int + *
    -double + *
    -float + *
    -char + *
    -String + *
    -byte[] + *
    -And the Wrappers Classes except for Byte + * + * Output: + *
    -WSReturnObject + *
    -byte[] + *
    -int + *
    -double + *
    -float + *
    -char + *
    -String + *
    -Arrays of Output + *
    -And the Wrappers Classes except for Byte + * + * @author Ziver + */ +public class SOAPHttpPage implements HttpPage{ + private static final Logger logger = LogUtil.getLogger(); + + /** The object that the functions will be invoked from **/ + private WebServiceDef wsDef; + /** This instance of the web service class is used if session is disabled **/ + private WSInterface ws; + /** Session enabled **/ + private boolean session_enabled; + + public SOAPHttpPage( WebServiceDef wsDef ){ + this.wsDef = wsDef; + this.session_enabled = false; + } + + /** + * Enables session support, if enabled then a new instance + * of the SOAPInterface will be created, if disabled then + * only the given object will be used as an static interface + * + * @param enabled is if session should be enabled + */ + public void enableSession(boolean enabled){ + this.session_enabled = enabled; + } + + /** + * Sets the web service object to the specified one. + * Only used when session is disabled + */ + public void setObject(WSInterface obj) { + this.ws = obj; + } + + + public void respond(HttpPrintStream out, + HttpHeader headers, + Map session, + Map cookie, + Map request) { + + try { + out.setHeader("Content-Type", "text/xml"); + out.flush(); + + WSInterface obj = null; + if(session_enabled){ + if( session.containsKey("SOAPInterface")) + obj = (WSInterface)session.get("SOAPInterface"); + else{ + obj = wsDef.newInstance(); + session.put("SOAPInterface", obj); + } + } + else{ + if( ws == null ) + ws = wsDef.newInstance(); + obj = ws; + } + + Document document = genSOAPResponse( request.get(""), obj); + + OutputFormat format = OutputFormat.createPrettyPrint(); + XMLWriter writer = new XMLWriter( out, format ); + writer.write( document ); + + + // DEBUG + if( logger.isLoggable(Level.FINEST) ){ + System.out.println("********** Request"); + System.out.println(request); + System.out.println("********** Response"); + writer = new XMLWriter( System.out, format ); + writer.write( document ); + } + } catch (Exception e) { + logger.log(Level.WARNING, "Unhandled request", e); + } + } + + /** + * Generates a soap response for the given XML + * + * @param xml is the XML request + * @return a Document with the response + */ + public Document genSOAPResponse(String xml){ + try { + WSInterface obj = null; + if( ws == null ) + ws = wsDef.newInstance(); + obj = ws; + + return genSOAPResponse(xml, obj ); + } catch (Exception e) { + logger.log(Level.WARNING, "Exception in SOAP generation", e); + } + return null; + } + + protected Document genSOAPResponse(String xml, WSInterface obj){ + Document document = DocumentHelper.createDocument(); + Element envelope = document.addElement("soap:Envelope"); + try { + envelope.addNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"); + envelope.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + envelope.addNamespace("xsd", "http://www.w3.org/2001/XMLSchema"); + + Element body = envelope.addElement( "soap:Body" ); + try{ + Element request = getXMLRoot(xml); + if(request == null) return document; + // Header + if( request.element("Header") != null){ + Element header = envelope.addElement( "soap:Header" ); + prepareInvoke( obj, request.element("Header"), header ); + } + + // Body + if( request.element("Body") != null){ + prepareInvoke( obj, request.element("Body"), body ); + } + }catch(Throwable e){ + body.clearContent(); + Element fault = body.addElement("soap:Fault"); + // The fault source + if(e instanceof SOAPException || e instanceof SAXException || e instanceof DocumentException) + fault.addElement("faultcode").setText( "soap:Client" ); + else + fault.addElement("faultcode").setText( "soap:Server" ); + // The fault message + if( e.getMessage() == null || e.getMessage().isEmpty()) + fault.addElement("faultstring").setText( ""+e.getClass().getSimpleName() ); + else + fault.addElement("faultstring").setText( ""+e.getMessage() ); + logger.log(Level.WARNING, "Caught exception from SOAP Class", e); + } + } catch (Exception e) { + logger.log(Level.WARNING, "Exception in SOAP generation", e); + } + + return document; + } + + /** + * Converts an String XML to an Element + * + * @param xml is the string XML + * @return the XML root Element + */ + protected static Element getXMLRoot(String xml) throws DocumentException { + if(xml != null && !xml.isEmpty()){ + Document document = DocumentHelper.parseText(xml); + return document.getRootElement(); + } + return null; + } + + /** + * Takes an XML Element and invokes all the it's child elements as methods. + * + * @param obj is the object that the methods will be called from + * @param requestRoot is the Element where the children lies + * @param responseRoot is the root element of the response + */ + @SuppressWarnings("unchecked") + private void prepareInvoke(WSInterface obj, Element requestRoot, Element responseRoot) throws Throwable{ + Iterator it = requestRoot.elementIterator(); + while( it.hasNext() ){ + Element e = it.next(); + if( wsDef.hasMethod( e.getQName().getName()) ){ + WSMethodDef m = wsDef.getMethod( e.getQName().getName() ); + Object[] params = new Object[ m.getInputCount() ]; + + // Get the parameter values + for(int i=0; i0 ){ + Element response = responseRoot.addElement(""); + response.addNamespace("m", m.getNamespace() ); + response.setName("m:"+m.getName()+"Response"); + + if( ret instanceof WSReturnObject ){ + Field[] f = ret.getClass().getFields(); + for(int i=0; i c){ + Class cTmp = getClass(c); + if(byte[].class.isAssignableFrom(c)){ + return "base64Binary"; + } + else if( WSReturnObject.class.isAssignableFrom(cTmp) ){ + return c.getSimpleName(); + } + else{ + String ret = c.getSimpleName().toLowerCase(); + + if(cTmp == Integer.class) ret = ret.replaceAll("integer", "int"); + else if(cTmp == Character.class)ret = ret.replaceAll("character", "char"); + + return ret; + } + } + + protected static Class getClass(Class c){ + if(c!=null && c.isArray()){ + return getClass(c.getComponentType()); + } + return c; + } +} + diff --git a/plugins/hal-vendor-ecosense/build.gradle b/src/zutil/osal/HalLinuxImpl.java similarity index 83% rename from plugins/hal-vendor-ecosense/build.gradle rename to src/zutil/osal/HalLinuxImpl.java index 0f6c5a03..21a025e1 100644 --- a/plugins/hal-vendor-ecosense/build.gradle +++ b/src/zutil/osal/HalLinuxImpl.java @@ -1,28 +1,33 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2025 Ziver Koc - * - * 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. - */ - -dependencies { - implementation project(':hal-core') - implementation 'software.amazon.awssdk:cognitoidentityprovider:2.35.10' -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal; + +/** + * Created by Ziver on 2015-04-07. + */ +public class HalLinuxImpl implements HardwareAbstractionLayer{ + + protected HalLinuxImpl(){} +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraConfig.java b/src/zutil/osal/HardwareAbstractionLayer.java similarity index 86% rename from plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraConfig.java rename to src/zutil/osal/HardwareAbstractionLayer.java index 77e76a9b..0c4343ee 100644 --- a/plugins/hal-nvr/src/se/hal/plugin/nvr/intf/HalCameraConfig.java +++ b/src/zutil/osal/HardwareAbstractionLayer.java @@ -1,31 +1,31 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.nvr.intf; - -import se.hal.intf.HalDeviceConfig; - -public interface HalCameraConfig extends HalDeviceConfig { - -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal; + +/** + * Created by Ziver on 2015-04-07. + */ +public interface HardwareAbstractionLayer { +} diff --git a/src/zutil/osal/OSAbstractionLayer.java b/src/zutil/osal/OSAbstractionLayer.java new file mode 100644 index 00000000..41d5e7d0 --- /dev/null +++ b/src/zutil/osal/OSAbstractionLayer.java @@ -0,0 +1,132 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; + +/** + * User: Ziver + */ +public abstract class OSAbstractionLayer { + public static enum OSType{ + Windows, Linux, MacOS, Unix + } + + // Variables + private static OSAbstractionLayer instance; + + public static OSAbstractionLayer getInstance(){ + if(instance == null) + instance = getAbstractionLayer(); + return instance; + } + + private static OSAbstractionLayer getAbstractionLayer(){ + String os = System.getProperty("os.name"); + if (os.contains("Linux")) return new OsalLinuxImpl(); + else if(os.contains("Windows")) return new OsalWindowsImpl(); + else return null; + } + + /** + * Executes a command and returns the first line of the result + * + * @param cmd the command to run + * @return first line of the command + */ + protected static String getFirstLineFromCommand(String cmd) { + String[] tmp = runCommand(cmd); + if(tmp.length > 1) + return tmp[0]; + return null; + } + + /** + * Executes a command and returns the result + * + * @param cmd the command to run + * @return a String list of the output of the command + */ + public static String[] runCommand(String cmd) { + ArrayList ret = new ArrayList(); + try { + Runtime runtime = Runtime.getRuntime(); + Process proc = runtime.exec(cmd); + proc.waitFor(); + BufferedReader output = new BufferedReader(new InputStreamReader(proc.getInputStream())); + + + String line; + while ((line = output.readLine()) != null) { + ret.add(line); + } + output.close(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return ret.toArray(new String[1]); + } + + /** + * @return the generic type of the OS + */ + public abstract OSType getOSType(); + + /** + * @return a more specific OS or distribution name e.g "ubuntu", "suse", "windows" + */ + public abstract String getOSName(); + + /** + * @return the OS version e.g windows: "vista", "7"; ubuntu: "10.4", "12.10" + */ + public abstract String getOSVersion(); + + public abstract String getKernelVersion(); + + /** + * @return the name of the current user + */ + public abstract String getUsername(); + + /** + * @return the path to the root folder for the current users configuration files e.g Linux: "/home/$USER" + */ + public abstract File getUserConfigPath(); + + /** + * @return the path to the global configuration folder e.g Linux: "/etc + */ + public abstract File getGlobalConfigPath(); + + public abstract HardwareAbstractionLayer getHAL(); +} diff --git a/src/zutil/osal/OsalLinuxImpl.java b/src/zutil/osal/OsalLinuxImpl.java new file mode 100644 index 00000000..327d4bed --- /dev/null +++ b/src/zutil/osal/OsalLinuxImpl.java @@ -0,0 +1,86 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal; + +import java.io.File; + +/** + * User: Ziver + */ +public class OsalLinuxImpl extends OSAbstractionLayer { + private static HalLinuxImpl hal; + + @Override + public OSType getOSType() { + return OSType.Linux; + } + + @Override + public String getOSName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String getOSVersion() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String getKernelVersion() { + try{ + return super.getFirstLineFromCommand("uname -r"); + } catch(Exception e){ + e.printStackTrace(); + } + return null; + } + + @Override + public String getUsername() { + try{ + return super.getFirstLineFromCommand("whoami"); + } catch(Exception e){ + e.printStackTrace(); + } + return null; + } + + @Override + public File getUserConfigPath() { + return new File("/home/"+getUsername()); + } + + @Override + public File getGlobalConfigPath() { + return new File("/etc"); + } + + @Override + public HardwareAbstractionLayer getHAL() { + if(hal == null) + hal = new HalLinuxImpl(); + return hal; + } +} diff --git a/plugins/hal-vendor-tibber/src/se/hal/plugin/vendor/tibber/device/TibberPowerConsumptionSensorConfig.java b/src/zutil/osal/OsalWindowsImpl.java similarity index 57% rename from plugins/hal-vendor-tibber/src/se/hal/plugin/vendor/tibber/device/TibberPowerConsumptionSensorConfig.java rename to src/zutil/osal/OsalWindowsImpl.java index fad3cd15..8f64ae79 100644 --- a/plugins/hal-vendor-tibber/src/se/hal/plugin/vendor/tibber/device/TibberPowerConsumptionSensorConfig.java +++ b/src/zutil/osal/OsalWindowsImpl.java @@ -1,61 +1,77 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024-2025 Ziver Koc - * - * 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. - */ - -package se.hal.plugin.vendor.tibber.device; - -import se.hal.intf.HalSensorConfig; -import se.hal.intf.HalSensorController; -import se.hal.intf.HalSensorData; -import se.hal.struct.devicedata.PowerConsumptionSensorData; -import se.hal.plugin.vendor.tibber.TibberController; - - -public class TibberPowerConsumptionSensorConfig implements HalSensorConfig { - - - @Override - public long getDataInterval() { - return 60*60 * 1000; // 1 min - } - - @Override - public AggregationMethod getAggregationMethod() { - return AggregationMethod.AVERAGE; - } - - @Override - public Class getDeviceControllerClass() { - return TibberController.class; - } - - @Override - public Class getDeviceDataClass() { - return PowerConsumptionSensorData.class; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TibberPowerConsumptionSensorConfig; - } -} +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal; + +import java.io.File; + +/** + * User: ezivkoc + */ +public class OsalWindowsImpl extends OSAbstractionLayer { + @Override + public OSType getOSType() { + return null; + } + + @Override + public String getOSName() { + return null; + } + + @Override + public String getOSVersion() { + return null; + } + + @Override + public String getKernelVersion() { + try { + return getFirstLineFromCommand("ver"); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + public String getUsername() { + return null; + } + + @Override + public File getUserConfigPath() { + return null; + } + + @Override + public File getGlobalConfigPath() { + return null; + } + + @Override + public HardwareAbstractionLayer getHAL() { + return null; + } +} diff --git a/src/zutil/osal/app/linux/AptGet.java b/src/zutil/osal/app/linux/AptGet.java new file mode 100644 index 00000000..2413a6d5 --- /dev/null +++ b/src/zutil/osal/app/linux/AptGet.java @@ -0,0 +1,173 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal.app.linux; + +import zutil.Timer; +import zutil.log.LogUtil; +import zutil.osal.OSAbstractionLayer; + +import java.util.HashMap; +import java.util.logging.Logger; + +/** + * Created by Ziver on 2014-11-09. + */ +public class AptGet { + public static final Logger log = LogUtil.getLogger(); + + private static Timer updateTimer = new Timer(1000*60*5); // 5min timer + private static Timer packageTimer = new Timer(1000*60*5); // 5min timer + private static HashMap packages = new HashMap<>(); + + public static void install(String pkg) { + update(); + OSAbstractionLayer.runCommand("apt-get -y install " + pkg); + packageTimer.reset(); + } + + public static void upgrade(){ + update(); + OSAbstractionLayer.runCommand("apt-get -y " + + // Dont display configuration conflicts + "-o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" " + + "upgrade"); + packageTimer.reset(); + } + + public static void update(){ + // Only run every 5 min + if(updateTimer.hasTimedOut()){ + OSAbstractionLayer.runCommand("apt-get update"); + updateTimer.start(); + } + } + + public static void purge(String pkg) { + OSAbstractionLayer.runCommand("apt-get --purge remove " + pkg); + packageTimer.reset(); + } + + + public static Package getPackage(String pkg){ + updatePackages(); + return packages.get(pkg); + } + public static synchronized void updatePackages(){ + // Only run every 5 min + if(packageTimer.hasTimedOut()){ + String[] output = OSAbstractionLayer.runCommand("dpkg --list"); + for(int i=5; i hdds = new HashMap(); + private static long updateTimestamp; + + + private synchronized static void update(){ + if(System.currentTimeMillis() - updateTimestamp < TTL) + return; + updateTimestamp = System.currentTimeMillis(); + try { + BufferedReader in = new BufferedReader(new FileReader(PROC_PATH)); + String line = null; + while((line=in.readLine()) != null){ + String[] str = line.trim().split("\\s+", 4); + if(str.length >= 4) { + String devName = str[2]; + if(!hdds.containsKey(devName)){ + HddStats hdd = new HddStats(devName); + hdds.put(hdd.getDevName(), hdd); + } + hdds.get(devName).update(str[3]); + } + } + in.close(); + } catch (IOException e) { + log.log(Level.SEVERE, null, e); + } + } + + public static HddStats getStats(String devName){ + update(); + return hdds.get(devName); + } + + + public static class HddStats { + private String devName; + //read I/Os requests number of read I/Os processed + private long readIO = -1; + //read merges requests number of read I/Os merged with in-queue I/O + private long readMerges = -1; + //read sectors sectors number of sectors read + private long readSectors = -1; + //read ticks milliseconds total wait time for read requests + private long readTicks = -1; + //write I/Os requests number of write I/Os processed + private long writeIO = -1; + //write merges requests number of write I/Os merged with in-queue I/O + private long writeMerges = -1; + //write sectors sectors number of sectors written + private long writeSectors = -1; + //write ticks milliseconds total wait time for write requests + private long writeTicks = -1; + //in_flight requests number of I/Os currently in flight + private long inFlight = -1; + //io_ticks milliseconds total time this block device has been active + private long ioTicks = -1; + //time_in_queue milliseconds total wait time for all requests + private long timeInQueue = -1; + + private ThroughputCalculator readThroughput; + private ThroughputCalculator writeThroughput; + + + protected HddStats(String devName) { + this.devName = devName; + readThroughput = new ThroughputCalculator(); + writeThroughput = new ThroughputCalculator(); + } + protected void update(String line){ + String[] stats = line.split("\\s+"); + if(stats.length >= 11){ + readIO = Long.parseLong(stats[0]); + readMerges = Long.parseLong(stats[1]); + readSectors = Long.parseLong(stats[2]); + readTicks = Long.parseLong(stats[3]); + writeIO = Long.parseLong(stats[4]); + writeMerges = Long.parseLong(stats[5]); + writeSectors = Long.parseLong(stats[6]); + writeTicks = Long.parseLong(stats[7]); + inFlight = Long.parseLong(stats[8]); + ioTicks = Long.parseLong(stats[9]); + timeInQueue = Long.parseLong(stats[10]); + + readThroughput.setTotalHandledData(readSectors * 512); + writeThroughput.setTotalHandledData(writeSectors * 512); + } + } + + + public String getDevName() { + return devName; + } + /** + * This values increment when an I/O request completes. + */ + public long getReadIO() { + return readIO; + } + /** + * This value increment when an I/O request is merged with an + * already-queued I/O request. + */ + public long getReadMerges() { + return readMerges; + } + /** + * This value count the number of sectors read from to this + * block device. The "sectors" in question are the standard UNIX 512-byte + * sectors, not any device- or filesystem-specific block size. The + * counter is incremented when the I/O completes. + */ + public long getReadSectors() { + return readSectors; + } + /** + * This value count the number of milliseconds that I/O requests have + * waited on this block device. If there are multiple I/O requests waiting, + * this value will increase at a rate greater than 1000/second; for + * example, if 60 read requests wait for an average of 30 ms, the read_ticks + * field will increase by 60*30 = 1800. + */ + public long getReadTicks() { + return readTicks; + } + /** + * This values increment when an I/O request completes. + */ + public long getWriteIO() { + return writeIO; + } + /** + * This value increment when an I/O request is merged with an + * already-queued I/O request. + */ + public long getWriteMerges() { + return writeMerges; + } + /** + * This value count the number of sectors written to this + * block device. The "sectors" in question are the standard UNIX 512-byte + * sectors, not any device- or filesystem-specific block size. The + * counter is incremented when the I/O completes. + */ + public long getWriteSectors() { + return writeSectors; + } + /** + * This value count the number of milliseconds that I/O requests have + * waited on this block device. If there are multiple I/O requests waiting, + * this value will increase at a rate greater than 1000/second; for + * example, if 60 write requests wait for an average of 30 ms, the write_ticks + * field will increase by 60*30 = 1800. + */ + public long getWriteTicks() { + return writeTicks; + } + /** + * This value counts the number of I/O requests that have been issued to + * the device driver but have not yet completed. It does not include I/O + * requests that are in the queue but not yet issued to the device driver. + */ + public long getInFlight() { + return inFlight; + } + /** + * This value counts the number of milliseconds during which the device has + * had I/O requests queued. + */ + public long getIoTicks() { + return ioTicks; + } + /** + * This value counts the number of milliseconds that I/O requests have waited + * on this block device. If there are multiple I/O requests waiting, this + * value will increase as the product of the number of milliseconds times the + * number of requests waiting (see "read ticks" above for an example). + */ + public long getTimeInQueue() { + return timeInQueue; + } + + /** + * @return the average byte/second read throughput from the disk + */ + public double getReadThroughput(){ + return readThroughput.getByteThroughput(); + } + /** + * @return the average byte/second write throughput to the disk + */ + public double getWriteThroughput(){ + return writeThroughput.getByteThroughput(); + } + } + + + public static void main(String[] args){ + while(true){ + HddStats hdd = ProcDiskstats.getStats("sda"); + System.out.println("sda= " + + "read: " + StringUtil.formatByteSizeToString((long)hdd.getReadThroughput()) + "/s "+ + "write: " + StringUtil.formatByteSizeToString((long)hdd.getWriteThroughput()) + "/s"); + try{Thread.sleep(1000);}catch (Exception e){} + } + } +} diff --git a/src/zutil/osal/app/linux/ProcStat.java b/src/zutil/osal/app/linux/ProcStat.java new file mode 100755 index 00000000..7dda6bc1 --- /dev/null +++ b/src/zutil/osal/app/linux/ProcStat.java @@ -0,0 +1,208 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal.app.linux; + +import zutil.Timer; +import zutil.log.LogUtil; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Documentation from https://www.kernel.org/doc/Documentation/block/stat.txt + * + * Created by ezivkoc on 2015-05-19. + */ +public class ProcStat { + private static final Logger log = LogUtil.getLogger(); + private static final String PROC_PATH = "/proc/stat"; + private static final int TTL = 500; // update stats every 0.5 second + + private static CpuStats cpuTotal = new CpuStats(); + private static ArrayList cpus = new ArrayList(); + private static long uptime; + private static long processes; + private static Timer updateTimer = new Timer(TTL); + + + private synchronized static void update(){ + if(updateTimer.hasTimedOut()) + return; + updateTimer.start(); + try { + BufferedReader in = new BufferedReader(new FileReader(PROC_PATH)); + String line = null; + while((line=in.readLine()) != null){ + String[] str = line.split("\\s+"); + if(str[0].equals("cpu")) { + cpuTotal.update(str); + } + else if(str[0].startsWith("cpu")){ + int cpuId = Integer.parseInt(str[0].substring(3)); + if(cpus.size() <= cpuId) + cpus.add(new CpuStats()); + cpus.get(cpuId).update(str); + } + else if(str[0].startsWith("btime")){ + uptime = Long.parseLong(str[1]); + } + else if(str[0].startsWith("processes")){ + processes = Long.parseLong(str[1]); + } + } + in.close(); + } catch (IOException e) { + log.log(Level.SEVERE, null, e); + } + } + + public static CpuStats getTotalCpuStats(){ + update(); + return cpuTotal; + } + public static Iterator getCpuStats(){ + update(); + return cpus.iterator(); + } + /** + * @return the time at which the system booted, in seconds since the Unix epoch. + */ + public static long getUptime(){ + update(); + return uptime; + } + /** + * @return the number of processes and threads created, which includes (but is not limited to) those created by calls to the fork() and clone() system calls. + */ + public static long getProcesses(){ + update(); + return processes; + } + + + + public static class CpuStats { + // normal processes executing in user mode + private long user; + // processes executing in kernel mode + private long system; + // twiddling thumbs + private long idle; + // waiting for I/O to complete + private long iowait; + private long steal; + // virtual processes + private long guest; + private long total; + + // Percentage + private float load_total; + private float load_user; + private float load_system; + private float load_iowait; + private float load_virtual; + + protected CpuStats(){} + protected void update(String[] stats){ + long newUser=0, newNice=0, newSystem=0, newIdle=0, newIowait=0, newIrq=0, newSoftirq=0, newSteal=0, newGuest=0, newGuestNice=0; + if(stats.length >= 1+8){ + newUser = Long.parseLong(stats[1]); + newNice = Long.parseLong(stats[2]); + newSystem = Long.parseLong(stats[3]); + newIdle = Long.parseLong(stats[4]); + newIowait = Long.parseLong(stats[5]); + newIrq = Long.parseLong(stats[6]); + newSoftirq = Long.parseLong(stats[7]); + if(stats.length >= 1+8+3){ + newSteal = Long.parseLong(stats[8]); + newGuest = Long.parseLong(stats[9]); + newGuestNice = Long.parseLong(stats[10]); + } + + // Summarize + newUser = newUser + newNice - newGuest - newGuestNice; + newSystem = newSystem + newIrq + newSoftirq; + newGuest = newGuest + newGuestNice; + + // Calculate the diffs + long userDiff = newUser - user; + long idleDiff = (newIdle + newIowait) - (idle + iowait); + long systemDiff = newSystem - system; + long stealDiff = newSteal - steal; + long virtualDiff = newGuest - guest; + long newTotal = userDiff + systemDiff + idleDiff + stealDiff + virtualDiff; + // Calculate load + load_total = (float)(newTotal-idleDiff)/newTotal; + load_user = (float)userDiff/newTotal; + load_system = (float)systemDiff/newTotal; + load_iowait = (float)(newIowait - iowait)/newTotal; + load_virtual = (float)virtualDiff/newTotal; + + // update old values + user = newUser; + system = newSystem; + idle = newIdle; + iowait = newIowait; + steal = newSteal; + guest = newGuest; + total = newTotal; + } + } + + public float getTotalLoad() { + return load_total; + } + public float getUserLoad() { + return load_user; + } + public float getSystemLoad() { + return load_system; + } + public float getIOWaitLoad() { + return load_iowait; + } + public float getVirtualLoad() { + return load_virtual; + } + + } + + public static void main(String[] args){ + while(true){ + Iterator it = ProcStat.getCpuStats(); + for(int i=0; it.hasNext(); ++i){ + CpuStats cpu = it.next(); + System.out.print("CPU"+i+": " + cpu.getTotalLoad()+ " "); + } + System.out.println("Total Load: " + ProcStat.getTotalCpuStats().getTotalLoad()); + try{Thread.sleep(1000);}catch (Exception e){} + } + } +} diff --git a/src/zutil/osal/app/linux/Ps.java b/src/zutil/osal/app/linux/Ps.java new file mode 100644 index 00000000..45c7cf9c --- /dev/null +++ b/src/zutil/osal/app/linux/Ps.java @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal.app.linux; + +import zutil.osal.OSAbstractionLayer; + +/** + * Created by Ziver on 2014-12-23. + */ +public class Ps { + private static OSAbstractionLayer os = OSAbstractionLayer.getInstance(); + + public static boolean isRunning(int pid){ + String[] output = os.runCommand("ps -p "+pid); + return output.length > 1; + } +} diff --git a/src/zutil/osal/app/windows/TypePerf.java b/src/zutil/osal/app/windows/TypePerf.java new file mode 100755 index 00000000..cdb79f8e --- /dev/null +++ b/src/zutil/osal/app/windows/TypePerf.java @@ -0,0 +1,77 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.osal.app.windows; + +import zutil.osal.OSAbstractionLayer; +import zutil.parser.CSVParser; +import zutil.parser.DataNode; + +import java.io.IOException; +import java.io.StringReader; + +/** + * Created by ezivkoc on 2015-07-30. + */ +public class TypePerf { + // Only available Vista and later... + //https://www.webperformance.com/support/suite/manual/Content/Locating_Server_Metric_Counters.htm + + /* + "(PDH-CSV 4.0)","\\SE00035694\processor(0)\% Processor Time","\\SE00035694\processor(0)\% User Time","\\SE00035694\processor(0)\% Privileged Time","\\SE00035694\processor(0)\Interrupts/sec","\\SE00035694\processor(0)\% DPC Time","\\SE00035694\processor(0)\% Interrupt Time","\\SE00035694\processor(0)\DPCs Queued/sec","\\SE00035694\processor(0)\DPC Rate","\\SE00035694\processor(0)\% Idle Time","\\SE00035694\processor(0)\% C1 Time","\\SE00035694\processor(0)\% C2 Time","\\SE00035694\processor(0)\% C3 Time","\\SE00035694\processor(0)\C1 Transitions/sec","\\SE00035694\processor(0)\C2 Transitions/sec","\\SE00035694\processor(0)\C3 Transitions/sec","\\SE00035694\processor(1)\% Processor Time","\\SE00035694\processor(1)\% User Time","\\SE00035694\processor(1)\% Privileged Time","\\SE00035694\processor(1)\Interrupts/sec","\\SE00035694\processor(1)\% DPC Time","\\SE00035694\processor(1)\% Interrupt Time","\\SE00035694\processor(1)\DPCs Queued/sec","\\SE00035694\processor(1)\DPC Rate","\\SE00035694\processor(1)\% Idle Time","\\SE00035694\processor(1)\% C1 Time","\\SE00035694\processor(1)\% C2 Time","\\SE00035694\processor(1)\% C3 Time","\\SE00035694\processor(1)\C1 Transitions/sec","\\SE00035694\processor(1)\C2 Transitions/sec","\\SE00035694\processor(1)\C3 Transitions/sec","\\SE00035694\processor(2)\% Processor Time","\\SE00035694\processor(2)\% User Time","\\SE00035694\processor(2)\% Privileged Time","\\SE00035694\processor(2)\Interrupts/sec","\\SE00035694\processor(2)\% DPC Time","\\SE00035694\processor(2)\% Interrupt Time","\\SE00035694\processor(2)\DPCs Queued/sec","\\SE00035694\processor(2)\DPC Rate","\\SE00035694\processor(2)\% Idle Time","\\SE00035694\processor(2)\% C1 Time","\\SE00035694\processor(2)\% C2 Time","\\SE00035694\processor(2)\% C3 Time","\\SE00035694\processor(2)\C1 Transitions/sec","\\SE00035694\processor(2)\C2 Transitions/sec","\\SE00035694\processor(2)\C3 Transitions/sec","\\SE00035694\processor(3)\% Processor Time","\\SE00035694\processor(3)\% User Time","\\SE00035694\processor(3)\% Privileged Time","\\SE00035694\processor(3)\Interrupts/sec","\\SE00035694\processor(3)\% DPC Time","\\SE00035694\processor(3)\% Interrupt Time","\\SE00035694\processor(3)\DPCs Queued/sec","\\SE00035694\processor(3)\DPC Rate","\\SE00035694\processor(3)\% Idle Time","\\SE00035694\processor(3)\% C1 Time","\\SE00035694\processor(3)\% C2 Time","\\SE00035694\processor(3)\% C3 Time","\\SE00035694\processor(3)\C1 Transitions/sec","\\SE00035694\processor(3)\C2 Transitions/sec","\\SE00035694\processor(3)\C3 Transitions/sec","\\SE00035694\processor(_Total)\% Processor Time","\\SE00035694\processor(_Total)\% User Time","\\SE00035694\processor(_Total)\% Privileged Time","\\SE00035694\processor(_Total)\Interrupts/sec","\\SE00035694\processor(_Total)\% DPC Time","\\SE00035694\processor(_Total)\% Interrupt Time","\\SE00035694\processor(_Total)\DPCs Queued/sec","\\SE00035694\processor(_Total)\DPC Rate","\\SE00035694\processor(_Total)\% Idle Time","\\SE00035694\processor(_Total)\% C1 Time","\\SE00035694\processor(_Total)\% C2 Time","\\SE00035694\processor(_Total)\% C3 Time","\\SE00035694\processor(_Total)\C1 Transitions/sec","\\SE00035694\processor(_Total)\C2 Transitions/sec","\\SE00035694\processor(_Total)\C3 Transitions/sec" + "07/30/2015 11:53:49.003","4.331731","4.629110","0.000000","1251.466768","0.000000","0.000000","58.368806","0.000000","95.668269","4.370950","3.882572","71.775440","219.624998","61.336711","1197.055170","4.331731","0.000000","1.543037","342.298420","1.543037","0.000000","147.405967","0.000000","98.754342","0.000000","0.000000","95.856588","0.000000","0.000000","341.309119","5.874768","6.172146","0.000000","1282.135124","0.000000","0.000000","23.743243","0.000000","94.125232","0.000000","0.000000","86.960208","0.000000","0.000000","1496.813613","4.331731","0.000000","0.000000","253.261259","0.000000","0.000000","19.786036","1.000000","100.297379","0.000000","0.000000","94.635420","0.000000","0.000000","265.132881","4.717488","2.700317","0.385757","3129.161571","0.385757","0.000000","249.304052","1.000000","97.211306","1.092740","0.970643","87.306914","219.624998","61.336711","3300.310781" + */ + private static final String PERF_CPU_PATH = "\\Processor(*)\\*"; + + /* + "(PDH-CSV 4.0)","\\SE00035694\Memory\Page Faults/sec","\\SE00035694\Memory\Available Bytes","\\SE00035694\Memory\Committed Bytes","\\SE00035694\Memory\Commit Limit","\\SE00035694\Memory\Write Copies/sec","\\SE00035694\Memory\Transition Faults/sec","\\SE00035694\Memory\Cache Faults/sec","\\SE00035694\Memory\Demand Zero Faults/sec","\\SE00035694\Memory\Pages/sec","\\SE00035694\Memory\Pages Input/sec","\\SE00035694\Memory\Page Reads/sec","\\SE00035694\Memory\Pages Output/sec","\\SE00035694\Memory\Pool Paged Bytes","\\SE00035694\Memory\Pool Nonpaged Bytes","\\SE00035694\Memory\Page Writes/sec","\\SE00035694\Memory\Pool Paged Allocs","\\SE00035694\Memory\Pool Nonpaged Allocs","\\SE00035694\Memory\Free System Page Table Entries","\\SE00035694\Memory\Cache Bytes","\\SE00035694\Memory\Cache Bytes Peak","\\SE00035694\Memory\Pool Paged Resident Bytes","\\SE00035694\Memory\System Code Total Bytes","\\SE00035694\Memory\System Code Resident Bytes","\\SE00035694\Memory\System Driver Total Bytes","\\SE00035694\Memory\System Driver Resident Bytes","\\SE00035694\Memory\System Cache Resident Bytes","\\SE00035694\Memory\% Committed Bytes In Use","\\SE00035694\Memory\Available KBytes","\\SE00035694\Memory\Available MBytes","\\SE00035694\Memory\Transition Pages RePurposed/sec","\\SE00035694\Memory\Free & Zero Page List Bytes","\\SE00035694\Memory\Modified Page List Bytes","\\SE00035694\Memory\Standby Cache Reserve Bytes","\\SE00035694\Memory\Standby Cache Normal Priority Bytes","\\SE00035694\Memory\Standby Cache Core Bytes" + "07/30/2015 11:54:52.288","1158.202545","1403789312.000000","7621783552.000000","18949070848.000000","0.000000","13.942249","1.991750","1142.268546","0.000000","0.000000","0.000000","0.000000","408887296.000000","184975360.000000","0.000000","430072.000000","242142.000000","33556038.000000","600846336.000000","650051584.000000","408686592.000000","4395008.000000","2433024.000000","19406848.000000","10178560.000000","600846336.000000","40.222466","1370888.000000","1338.000000","0.000000","25022464.000000","46465024.000000","24576.000000","1378742272.000000","0.000000" + */ + private static final String PERF_MEM_PATH = "\\Memory\\*"; + + /* + "(PDH-CSV 4.0)","\\SE00035694\PhysicalDisk(0 C: D: E:)\Current Disk Queue Length","\\SE00035694\PhysicalDisk(0 C: D: E:)\% Disk Time","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk Queue Length","\\SE00035694\PhysicalDisk(0 C: D: E:)\% Disk Read Time","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk Read Queue Length","\\SE00035694\PhysicalDisk(0 C: D: E:)\% Disk Write Time","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk Write Queue Length","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk sec/Transfer","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk sec/Read","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk sec/Write","\\SE00035694\PhysicalDisk(0 C: D: E:)\Disk Transfers/sec","\\SE00035694\PhysicalDisk(0 C: D: E:)\Disk Reads/sec","\\SE00035694\PhysicalDisk(0 C: D: E:)\Disk Writes/sec","\\SE00035694\PhysicalDisk(0 C: D: E:)\Disk Bytes/sec","\\SE00035694\PhysicalDisk(0 C: D: E:)\Disk Read Bytes/sec","\\SE00035694\PhysicalDisk(0 C: D: E:)\Disk Write Bytes/sec","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk Bytes/Transfer","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk Bytes/Read","\\SE00035694\PhysicalDisk(0 C: D: E:)\Avg. Disk Bytes/Write","\\SE00035694\PhysicalDisk(0 C: D: E:)\% Idle Time","\\SE00035694\PhysicalDisk(0 C: D: E:)\Split IO/Sec","\\SE00035694\PhysicalDisk(_Total)\Current Disk Queue Length","\\SE00035694\PhysicalDisk(_Total)\% Disk Time","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk Queue Length","\\SE00035694\PhysicalDisk(_Total)\% Disk Read Time","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk Read Queue Length","\\SE00035694\PhysicalDisk(_Total)\% Disk Write Time","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk Write Queue Length","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk sec/Transfer","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk sec/Read","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk sec/Write","\\SE00035694\PhysicalDisk(_Total)\Disk Transfers/sec","\\SE00035694\PhysicalDisk(_Total)\Disk Reads/sec","\\SE00035694\PhysicalDisk(_Total)\Disk Writes/sec","\\SE00035694\PhysicalDisk(_Total)\Disk Bytes/sec","\\SE00035694\PhysicalDisk(_Total)\Disk Read Bytes/sec","\\SE00035694\PhysicalDisk(_Total)\Disk Write Bytes/sec","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk Bytes/Transfer","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk Bytes/Read","\\SE00035694\PhysicalDisk(_Total)\Avg. Disk Bytes/Write","\\SE00035694\PhysicalDisk(_Total)\% Idle Time","\\SE00035694\PhysicalDisk(_Total)\Split IO/Sec" + "07/30/2015 11:55:26.544","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","100.148515","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","100.148515","0.000000" + */ + private static final String PERF_DISK_PATH = "\\PhysicalDisk(*)\\*"; + + /* + "(PDH-CSV 4.0)","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Bytes Total/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Received/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Sent/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Current Bandwidth","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Bytes Received/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Received Unicast/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Received Discarded","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Received Errors","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Received Unknown","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Bytes Sent/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Sent Unicast/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Outbound Discarded","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Packets Outbound Errors","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Output Queue Length","\\SE00035694\Network Interface(Intel[R] Ethernet Connection I218-LM)\Offloaded Connections","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Bytes Total/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Received/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Sent/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Current Bandwidth","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Bytes Received/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Received Unicast/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Received Discarded","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Received Errors","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Received Unknown","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Bytes Sent/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Sent Unicast/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Outbound Discarded","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Packets Outbound Errors","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Output Queue Length","\\SE00035694\Network Interface(Intel[R] Dual Band Wireless-N 7260)\Offloaded Connections","\\SE00035694\Network Interface(6TO4 Adapter)\Bytes Total/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Received/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Sent/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Current Bandwidth","\\SE00035694\Network Interface(6TO4 Adapter)\Bytes Received/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Received Unicast/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Received Discarded","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Received Errors","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Received Unknown","\\SE00035694\Network Interface(6TO4 Adapter)\Bytes Sent/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Sent Unicast/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Outbound Discarded","\\SE00035694\Network Interface(6TO4 Adapter)\Packets Outbound Errors","\\SE00035694\Network Interface(6TO4 Adapter)\Output Queue Length","\\SE00035694\Network Interface(6TO4 Adapter)\Offloaded Connections","\\SE00035694\Network Interface(Local Area Connection* 12)\Bytes Total/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Received/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Sent/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Current Bandwidth","\\SE00035694\Network Interface(Local Area Connection* 12)\Bytes Received/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Received Unicast/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Received Discarded","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Received Errors","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Received Unknown","\\SE00035694\Network Interface(Local Area Connection* 12)\Bytes Sent/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Sent Unicast/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Outbound Discarded","\\SE00035694\Network Interface(Local Area Connection* 12)\Packets Outbound Errors","\\SE00035694\Network Interface(Local Area Connection* 12)\Output Queue Length","\\SE00035694\Network Interface(Local Area Connection* 12)\Offloaded Connections","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Bytes Total/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Received/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Sent/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Current Bandwidth","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Bytes Received/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Received Unicast/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Received Discarded","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Received Errors","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Received Unknown","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Bytes Sent/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Sent Unicast/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Outbound Discarded","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Packets Outbound Errors","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Output Queue Length","\\SE00035694\Network Interface(isatap.ki.sw.ericsson.se)\Offloaded Connections","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Bytes Total/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Received/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Sent/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Current Bandwidth","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Bytes Received/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Received Unicast/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Received Discarded","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Received Errors","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Received Unknown","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Bytes Sent/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Sent Unicast/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Outbound Discarded","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Packets Outbound Errors","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Output Queue Length","\\SE00035694\Network Interface(isatap.{B9D01222-E737-4A0B-8321-7FE782CD4197})\Offloaded Connections","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Bytes Total/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Received/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Sent/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Current Bandwidth","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Bytes Received/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Received Unicast/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Received Discarded","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Received Errors","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Received Unknown","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Bytes Sent/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Sent Unicast/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Outbound Discarded","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Packets Outbound Errors","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Output Queue Length","\\SE00035694\Network Interface(isatap.{BA17492A-F69D-42F3-890A-3E9B8D2DA7C9})\Offloaded Connections","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Bytes Total/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Received/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Sent/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Current Bandwidth","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Bytes Received/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Received Unicast/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Received Non-Unicast/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Received Discarded","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Received Errors","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Received Unknown","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Bytes Sent/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Sent Unicast/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Sent Non-Unicast/sec","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Outbound Discarded","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Packets Outbound Errors","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Output Queue Length","\\SE00035694\Network Interface(isatap.{A42279F6-5D04-468C-A354-23EC38A4D962})\Offloaded Connections" + "07/30/2015 11:56:40.899","6479.124376","13.269125","9.477947","3.791179","100000000.000000","6183.412438","5.686768","3.791179","0.000000","0.000000","0.000000","295.711938","3.791179","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","300000000.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","30000000.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","100000.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","100000.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","100000.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","100000.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","100000.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000","0.000000" + */ + private static final String PERF_NET_PATH = "\\Network Interface(*)\\*"; + + + + private static DataNode[] execute(String path) throws IOException { + DataNode[] ret = new DataNode[2]; + + String[] output = OSAbstractionLayer.runCommand("typeperf \""+ path +"\" -SC 0 -y"); + CSVParser parser = new CSVParser(new StringReader(output[1] + "\n" + output[2])); + + ret[0] = parser.getHeaders(); + ret[1] = parser.read(); + return ret; + } +} diff --git a/src/zutil/parser/BBCodeParser.java b/src/zutil/parser/BBCodeParser.java new file mode 100755 index 00000000..42b6a4e2 --- /dev/null +++ b/src/zutil/parser/BBCodeParser.java @@ -0,0 +1,187 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import zutil.struct.MutableInt; + +import java.util.HashMap; + +/** + * Parses BBCode and replaces them with the corresponding HTML. + * + * @author Ziver + */ +public class BBCodeParser { + /** Contains all the BBCodes and the corresponding HTML **/ + private HashMap bbcodes; + + + /** + * Initiates a instance of the parser with the most used BBCodes. + */ + public BBCodeParser(){ + bbcodes = new HashMap(); + addBBCode("b", "%2"); + addBBCode("i", "%2"); + addBBCode("u", "%2"); + addBBCode("url", "%2"); + addBBCode("img", ""); + addBBCode("quote", "
    %2
    "); + addBBCode("code", "
    %2
    "); + addBBCode("size", "%2"); + addBBCode("color", "%2"); + addBBCode("ul", "
      %2
    "); + addBBCode("li", "
  • %2
  • "); + } + + /** + * Registers a new BBCode to the parser. Only one type of BBCode allowed. + * + * @param bbcode is the BBCode e.g. "b" or "url" + * @param html is the corresponding HTML e.g. "%2" + * where the %x corresponds to BBCode like this: [url=%1]%2[/url] + */ + public void addBBCode(String bbcode, String html){ + bbcodes.put(bbcode, html); + } + + /** + * Removes a BBCode definition from the parser + * + * @param bbcode is the bbcode to remove + */ + public void removeBBCode(String bbcode){ + bbcodes.remove(bbcode); + } + + /** + * Parses the text with BBCode and converts it to HTML + * + * @param text is a String with BBCode + * @return a String where all BBCode has been replaced by HTML + */ + public String read(String text){ + StringBuilder out = new StringBuilder(); + StringBuilder t = new StringBuilder(text); + + read(new MutableInt(), t, out, ""); + + return out.toString(); + } + + private void read(MutableInt index, StringBuilder text, StringBuilder out, String rootBBC){ + StringBuilder bbcode = null; + boolean closeTag = false; + while(index.i < text.length()){ + char c = text.charAt(index.i); + if(c == '['){ + bbcode = new StringBuilder(); + } + else if(bbcode!=null && c == '/'){ + closeTag = true; + } + else if(bbcode!=null){ + String param = ""; + switch(c){ + case '=': + param = parseParam(index, text); + case ']': + String bbcode_cache = bbcode.toString(); + if(closeTag){ + if(!rootBBC.equals(bbcode_cache)){ + out.append("[/").append(bbcode).append("]"); + } + return; + } + String value = parseValue(index, text, bbcode_cache); + if(bbcodes.containsKey( bbcode_cache )){ + String html = bbcodes.get( bbcode_cache ); + html = html.replaceAll("%1", param); + html = html.replaceAll("%2", value); + out.append(html); + } + else{ + out.append('[').append(bbcode); + if(!param.isEmpty()) + out.append('=').append(param); + out.append(']').append(value); + out.append("[/").append(bbcode).append("]"); + } + bbcode = null; + break; + default: + bbcode.append(c); + break; + } + } + else + out.append(c); + + index.i++; + } + if(bbcode!=null) + if(closeTag)out.append("[/").append(bbcode); + else out.append('[').append(bbcode); + } + + /** + * Parses a parameter from a BBCode block: [url=param] + * + * @param text is the text to parse from + * @return only the parameter string + */ + private String parseParam(MutableInt index, StringBuilder text){ + StringBuilder param = new StringBuilder(); + while(index.i < text.length()){ + char c = text.charAt(index.i); + if(c == ']') + break; + else if(c != '=') + param.append(c); + index.i++; + } + return param.toString(); + } + + /** + * Parses the value in the BBCodes e.g. [url]value[/url] + * + * @param text is the text to parse the value from + */ + private String parseValue(MutableInt index, StringBuilder text, String bbcode){ + StringBuilder value = new StringBuilder(); + while(index.i < text.length()){ + char c = text.charAt(index.i); + if(c == '['){ + read(index, text, value, bbcode); + break; + } + else if(c != ']') + value.append(c); + index.i++; + } + return value.toString(); + } +} diff --git a/src/zutil/parser/BEncodedParser.java b/src/zutil/parser/BEncodedParser.java new file mode 100755 index 00000000..449308ef --- /dev/null +++ b/src/zutil/parser/BEncodedParser.java @@ -0,0 +1,118 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import zutil.parser.DataNode.DataType; +import zutil.struct.MutableInt; + +/** + * http://wiki.theory.org/BitTorrentSpecification + * @author Ziver + * + */ +public class BEncodedParser { + + /** + * Returns the representation of the data in the BEncoded string + * + * @param data is the data to be decoded + * @return + */ + public static DataNode read(String data){ + return decode_BEncoded(new MutableInt(), new StringBuilder(data)); + } + + /** + * Returns the representation of the data in the BEncoded string + * + * @param data is the data to be decoded + * @param index is the index in data to start from + * @return + */ + private static DataNode decode_BEncoded(MutableInt index, StringBuilder data){ + String tmp; + char c = ' '; + + switch (data.charAt(index.i)) { + /** + * Integers are prefixed with an i and terminated by an e. For + * example, 123 would bEcode to i123e, -3272002 would bEncode to + * i-3272002e. + */ + case 'i': + index.i++; + tmp = data.substring(index.i, data.indexOf("e")); + index.i += tmp.length() + 1; + return new DataNode( new Long(tmp)); + /** + * Lists are prefixed with a l and terminated by an e. The list + * should contain a series of bEncoded elements. For example, the + * list of strings ["Monduna", "Bit", "Torrents"] would bEncode to + * l7:Monduna3:Bit8:Torrentse. The list [1, "Monduna", 3, ["Sub", "List"]] + * would bEncode to li1e7:Mondunai3el3:Sub4:Listee + */ + case 'l': + index.i++; + DataNode list = new DataNode( DataType.List ); + c = data.charAt(index.i); + while(c != 'e'){ + list.add( decode_BEncoded(index, data) ); + c = data.charAt(index.i); + } + index.i++; + if(list.size() == 1) return list.get(0); + else return list; + /** + * Dictionaries are prefixed with a d and terminated by an e. They + * are similar to list, except that items are in key value pairs. The + * dictionary {"key":"value", "Monduna":"com", "bit":"Torrents", "number":7} + * would bEncode to d3:key5:value7:Monduna3:com3:bit:8:Torrents6:numberi7ee + */ + case 'd': + index.i++; + DataNode map = new DataNode( DataType.Map ); + c = data.charAt(index.i); + while(c != 'e'){ + DataNode tmp2 = decode_BEncoded(index, data); + map.set(tmp2.getString(), decode_BEncoded(index, data)); + c = data.charAt(index.i); + } + index.i++; + return map; + /** + * Strings are prefixed with their length followed by a colon. + * For example, "Monduna" would bEncode to 7:Monduna and "BitTorrents" + * would bEncode to 11:BitTorrents. + */ + default: + tmp = data.substring(index.i, data.indexOf(":")); + int length = Integer.parseInt(tmp); + index.i += tmp.length() + 1; + String ret = data.substring(index.i, length); + index.i += length; + return new DataNode( ret ); + } + } +} diff --git a/src/zutil/parser/Base64Decoder.java b/src/zutil/parser/Base64Decoder.java new file mode 100755 index 00000000..1455a94e --- /dev/null +++ b/src/zutil/parser/Base64Decoder.java @@ -0,0 +1,196 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import zutil.converter.Converter; +import zutil.io.DynamicByteArrayStream; + +public class Base64Decoder { + public static final char[] B64_ENCODE_TABLE = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + + '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '+', '/' + }; + + private DynamicByteArrayStream output; + private byte rest_data; + private int rest = 0; + + public Base64Decoder(){ + output = new DynamicByteArrayStream(); + } + + + public static String decode( String data ){ + Base64Decoder base64 = new Base64Decoder(); + base64.read( data ); + return base64.toString(); + } + + public static String decodeToHex( String data ){ + Base64Decoder base64 = new Base64Decoder(); + base64.read( data ); + return Converter.toHexString( base64.getByte() ); + } + + public static byte[] decodeToByte( String data ){ + Base64Decoder base64 = new Base64Decoder(); + base64.read( data ); + return base64.getByte(); + } + + public void read( String data ){ + byte[] buffer = new byte[ (data.length()*6/8) + 1 ]; + int buffi = 0; + if( rest != 0 ) + buffer[0] = rest_data; + + for( int i=0; i> 2) & 0b0011_1111); + break; + case 2: + b = (byte) ((data[i-1] << 4) & 0b0011_0000); + b |= (byte) ((data[i] >> 4) & 0b0000_1111); + break; + case 4: + b = (byte) ((data[i-1] << 2) & 0b0011_1100); + b |= (byte) ((data[i] >> 6) & 0b0000_0011); + break; + case 6: + --i; // Go back one element + b = (byte) (data[i] & 0b0011_1111); + break; + } + + rest = (rest + 2) % 8; + buffer[buffIndex++] = getChar(b); + } + // Any rest left? + if(rest == 2) + buffer[buffIndex++] = getChar((byte) ((data[data.length-1] << 4) & 0b0011_0000)); + else if(rest == 4) + buffer[buffIndex++] = getChar((byte) ((data[data.length-1] << 2) & 0b0011_1100)); + else if(rest == 6) + buffer[buffIndex++] = getChar((byte) (data[data.length-1] & 0b0011_1111)); + + // Add padding + for(; buffIndex= 0 && c != '\n'){ + if(c == delimiter && !quoteStarted){ + data.add(value.toString()); + value.delete(0, value.length()); // Reset StringBuilder + } + else if(c == '\"' && // Ignored quotes + (value.length() == 0 || quoteStarted)){ + quoteStarted = !quoteStarted; + } + else + value.append((char)c); + } + if(value.length() > 0) + data.add(value.toString()); + if(data.size() == 0) + return null; + return data; + } +} diff --git a/src/zutil/parser/DataNode.java b/src/zutil/parser/DataNode.java new file mode 100644 index 00000000..34a8bd8f --- /dev/null +++ b/src/zutil/parser/DataNode.java @@ -0,0 +1,342 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import java.util.*; + + +/** + * This is a data node used in JSON and BEncoding and other types + * + * @author Ziver + */ +public class DataNode implements Iterable{ + public enum DataType{ + Map, List, String, Number, Boolean + } + private Map map = null; + private List list = null; + private String value = null; + private DataType type; + + + /** + * Creates an instance with an Boolean value + */ + public DataNode(boolean value){ + this.type = DataType.Boolean; + this.value = ""+value; + } + /** + * Creates an instance with an int value + */ + public DataNode(int value){ + this.type = DataType.Number; + this.value = ""+value; + } + /** + * Creates an instance with an double value + */ + public DataNode(double value){ + this.type = DataType.Number; + this.value = ""+value; + } + /** + * Creates an instance with an long value + */ + public DataNode(long value){ + this.type = DataType.Number; + this.value = ""+value; + } + /** + * Creates an instance with an String value + */ + public DataNode(String value){ + this.type = DataType.String; + this.value = value; + } + /** + * Creates an instance with a specific type + */ + public DataNode(DataType type){ + this.type = type; + switch(type){ + case Map: + map = new HashMap(); break; + case List: + list = new LinkedList(); break; + default: + break; + } + } + + /** + * @param index is the index of the List or Map + * @return an JSONNode that contains the next level of the List or Map + */ + public DataNode get(int index){ + if(map != null) + return map.get(""+index); + else if(list != null) + return list.get(index); + return null; + } + /** + * @param index is the key in the Map + * @return an JSONNode that contains the next level of the Map + */ + public DataNode get(String index){ + if(map != null) + return map.get(index); + return null; + } + + /** + * @return a iterator for the Map or List or null if the node contains a value + */ + public Iterator iterator(){ + if(map != null) + return map.values().iterator(); + else if(list != null) + return list.iterator(); + return null; + } + /** + * @return a iterator for the keys in the Map or null if the node contains a value or List + */ + public Iterator keyIterator(){ + if(map != null) + return map.keySet().iterator(); + return null; + } + /** + * @return the size of the Map or List or -1 if it is a value + */ + public int size(){ + if(map != null) + return map.size(); + else if(list != null) + return list.size(); + return -1; + } + + + /** + * Adds a node to the List + */ + public void add(DataNode node){ + list.add(node); + } + public void add(boolean value){ + list.add(new DataNode( value )); + } + public void add(int value){ + list.add(new DataNode( value )); + } + public void add(double value){ + list.add(new DataNode( value )); + } + public void add(long value){ + list.add(new DataNode( value )); + } + public void add(String value){ + list.add(new DataNode( value )); + } + /** + * Adds a node to the Map + */ + public void set(String key, DataNode node){ + map.put(key, node); + } + public void set(String key, boolean value){ + map.put(key, new DataNode(value)); + } + public void set(String key, int value){ + map.put(key, new DataNode(value)); + } + public void set(String key, double value){ + map.put(key, new DataNode(value)); + } + public void set(String key, long value){ + map.put(key, new DataNode(value)); + } + public void set(String key, String value){ + map.put(key, new DataNode(value)); + } + /** + * Sets the value of the node + * @exception NullPointerException if the node is setup as anything other than a DataType.Number + */ + public void set(int value){ + if( this.type != DataType.Number ) + throw new NullPointerException("The node is not setup as a DataType.Number"); + this.value = ""+value; + } + /** + * Sets the value of the node + * @exception NullPointerException if the node is setup as anything other than a DataType.Number + */ + public void set(double value){ + if( this.type != DataType.Number ) + throw new NullPointerException("The node is not setup as a DataType.Number"); + this.value = ""+value; + } + /** + * Sets the value of the node + * @exception NullPointerException if the node is setup as anything other than a DataType.Boolean + */ + public void set(boolean value){ + if( this.type != DataType.Boolean ) + throw new NullPointerException("The node is not setup as a DataType.Boolean"); + this.value = ""+value; + } + /** + * Sets the value of the node, but only + * @exception NullPointerException if the node is setup as anything other than a DataType.Number + */ + public void set(long value){ + if( this.type != DataType.Number ) + throw new NullPointerException("The node is not setup as a DataType.Number"); + this.value = ""+value; + } + /** + * Sets the value of the node + * @exception NullPointerException if the method DataType.isValue() returns false + */ + public void set(String value){ + if( !this.isValue() ) throw new NullPointerException("The node is not setup as a value node"); + this.value = value; + } + + + /** + * @return if this node contains an Map + */ + public boolean isMap(){ + return type == DataType.Map; + } + /** + * @return if this node contains an List + */ + public boolean isList(){ + return type == DataType.List; + } + /** + * @return if this node contains an value + */ + public boolean isValue(){ + return type != DataType.Map && type != DataType.List; + } + /** + * @return the type of the node + */ + public DataType getType(){ + return type; + } + + + /** + * @return the String value in this map + */ + public String getString(String key){ + if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map"); + if( !this.map.containsKey(key) ) + return null; + return this.get(key).getString(); + } + /** + * @return the boolean value in this map + */ + public boolean getBoolean(String key){ + if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map"); + if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map"); + return this.get(key).getBoolean(); + } + /** + * @return the integer value in this map + */ + public int getInt(String key){ + if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map"); + if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map"); + return this.get(key).getInt(); + } + /** + * @return the double value in this map + */ + public double getDouble(String key){ + if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map"); + if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map"); + return this.get(key).getDouble(); + } + /** + * @return the long value in this map + */ + public long getLong(String key){ + if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map"); + if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map"); + return this.get(key).getLong(); + } + + + /** + * @return the String value in this node, null if its a Map or List + */ + public String getString(){ + return value; + } + /** + * @return the boolean value in this node + */ + public boolean getBoolean(){ + return Boolean.parseBoolean(value); + } + /** + * @return the integer value in this node + */ + public int getInt(){ + return Integer.parseInt(value); + } + /** + * @return the double value in this node + */ + public double getDouble(){ + return Double.parseDouble(value); + } + /** + * @return the long value in this node + */ + public long getLong(){ + return Long.parseLong(value); + } + + + public String toString(){ + if( this.isMap() ) + return map.toString(); + else if( this.isList() ) + return list.toString(); + return value; + } +} diff --git a/src/zutil/parser/MathParser.java b/src/zutil/parser/MathParser.java new file mode 100644 index 00000000..f90b47b3 --- /dev/null +++ b/src/zutil/parser/MathParser.java @@ -0,0 +1,257 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * This class parses a string with math + * and solves it + * + * @author Ziver + */ +public class MathParser { + + public static MathNode parse(String functionString){ + StringBuffer functionStringBuffer = new StringBuffer(functionString+(char)0); + MathNode node = new MathNode(); + + parse(functionStringBuffer, new StringBuffer(), null, node); + + System.out.println("----------------------------------------------------------------------"); + System.out.println(node+" = "+node.exec()); + System.out.println("----------------------------------------------------------------------"); + return node; + } + + private static void parse(StringBuffer functionString, StringBuffer temp, MathOperation previus, MathNode rootNode){ + if(functionString.length() <= 0){ + return; + } + char c = functionString.charAt(0); + functionString.deleteCharAt(0); + System.out.println("char: "+c); + MathOperation current = null; + + if(!Character.isWhitespace(c)){ + if(isNumber(c)){ + temp.append(c); + } + else{ + Math container = new MathNumber(); + if(temp.length() > 0){ + System.out.println("("+Double.parseDouble(temp.toString())+")"); + ((MathNumber)container).num = Double.parseDouble(temp.toString()); + temp.delete(0, temp.length()); + } + + if(rootNode.math == null){ + System.out.println("Initializing rootNode"); + previus = getOperation(c); + System.out.println("operation: "+previus.getClass().getName()); + previus.math1 = container; + rootNode.math = previus; + } + else{ + if(c == '('){ + MathNode parenteses = new MathNode(); + MathOperation previousParanteses = previus; + parse(functionString, temp, previus, parenteses); + previousParanteses.math2 = parenteses; + System.out.println(parenteses); + container = parenteses; + + // get the next operation + c = functionString.charAt(0); + functionString.deleteCharAt(0); + System.out.println("char: "+c); + } + + current = getOperation(c); + System.out.println("operation: "+current.getClass().getName()); + current.math1 = container; + previus.math2 = current; + + if(c == ')'){ + return; + } + } + } + } + + if(current != null) parse(functionString, temp, current, rootNode); + else parse(functionString, temp, previus, rootNode); + return; + } + + private static boolean isNumber(char c){ + if(Character.isDigit(c)){ + return true; + } + return false; + } + + private static MathOperation getOperation(char c){ + switch(c){ + case '+': return new MathAddition(); + case '-': return new MathSubtraction(); + case '*': return new MathMultiplication(); + case '/': return new MathDivision(); + case '%': return new MathModulus(); + case '^': return new MathPow(); + case ')': + case (char)0: return new EmptyMath(); + default: return null; + } + } + + public static void main(String[] args){ + try { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + while(true){ + System.out.print(">>Math: "); + parse(in.readLine()); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + static abstract class Math{ + public abstract double exec(); + + public abstract String toString(); + } + + static class MathNode extends Math{ + Math math; + + public double exec() { + return math.exec(); + } + + public String toString() { + return "( "+math.toString()+" )"; + } + } + + static class MathNumber extends Math{ + double num; + + public double exec() { + return num; + } + + public String toString() { + return ""+num; + } + } + + static abstract class MathOperation extends Math{ + Math math1; + Math math2; + + public abstract double exec(); + } + + static class MathAddition extends MathOperation{ + public double exec() { + return math1.exec() + math2.exec(); + } + + public String toString() { + return math1.toString()+" + "+math2.toString(); + } + } + + static class MathSubtraction extends MathOperation{ + public double exec() { + return math1.exec() - math2.exec(); + } + + public String toString() { + return math1.toString()+" - "+math2.toString(); + } + } + + static class MathMultiplication extends MathOperation{ + public double exec() { + return math1.exec() * math2.exec(); + } + + public String toString() { + return math1.toString()+" * "+math2.toString(); + } + } + + static class MathDivision extends MathOperation{ + public double exec() { + return math1.exec() / math2.exec(); + } + + public String toString() { + return math1.toString()+" / "+math2.toString(); + } + } + + static class MathModulus extends MathOperation{ + public double exec() { + return math1.exec() % math2.exec(); + } + + public String toString() { + return math1.toString()+" % "+math2.toString(); + } + } + + static class MathPow extends MathOperation{ + public double exec() { + double ret = 1; + double tmp1 = math1.exec(); + double tmp2 = math2.exec(); + for(int i=0; i
    + * Supported tags: + *
      + *
    • {{key}}
      + * {{obj.attr}}
      + * Will be replaced with the string from the key.
    • + *
    • {{#key}}...{{/key}}
      + * {{#obj.attr}}...{{/obj.attr}}
      + * Will display content between the tags if: + *
        + *
      • key is defined,
      • + *
      • if the key references a list or array the content will be iterated + * for every element, the element can be referenced by the tag {{.}},
      • + *
      • if key is a boolean with the value true,
      • + *
      • if key is a Integer with the value anything other then 0,
      • + *
      • if key ends with () it will be evaluated as a method call, the returned + * type will be evaluated against the criteria in this list.
      • + *
      + *
    • + *
    • {{^key}}
      + * {{^obj.attr}}...{{/obj.attr}}
      + * A negative condition, will display content if: + *
        + *
      • the key is undefined,
      • + *
      • the key is a empty list,
      • + *
      • the key is a zero length array,
      • + *
      • the key is a false boolean,
      • + *
      • the key is a 0 Integer
      • + *
      • if key ends with () it will be evaluated as a method call, the returned + * type will be evaluated against the criteria in this list.
      • + *
      + *
    • + *
    • {{! ignore me }}
      + * Comment, will be ignored.
    • + *
    + * + * TODO: {{> file}}: include file + * TODO: {{=<% %>=}}: change delimiter + * + * @author Ziver koc + */ +public class Templator { + private static final Logger log = LogUtil.getLogger(); + + private HashMap data; + private TemplateEntity tmplRoot; + + // File metadata + private File file; + private long lastModified; + + /** + * A template file will be read from the disk. The template will + * be regenerated if the file changes. + */ + public Templator(File tmpl) throws IOException { + if(tmpl == null) + throw new IllegalArgumentException("File can not be null!"); + this.data = new HashMap(); + this.file = tmpl; + parseTemplate(FileUtil.getContent(file)); + this.lastModified = file.lastModified(); + } + public Templator(String tmpl){ + this.data = new HashMap(); + parseTemplate(tmpl); + } + + + public void set(String key, Object data){ + this.data.put(key, data); + } + public Object get(String key){ + return this.data.get(key); + } + public void remove(String key){ + this.data.remove(key); + } + + /** + * Will clear all data attributes + */ + public void clear(){ + data.clear(); + } + + public String compile(){ + if(file != null && lastModified != file.lastModified()){ + try { + log.info("Template file("+file.getName()+") changed. Regenerating template..."); + parseTemplate(FileUtil.getContent(file)); + this.lastModified = file.lastModified(); + } catch(IOException e) { + log.log(Level.WARNING, "Unable to regenerate template", e); + } + } + + StringBuilder str = new StringBuilder(); + if(tmplRoot != null) + tmplRoot.compile(str); + return str.toString(); + } + + /** + * Will parse or re-parse the source template. + */ + private void parseTemplate(String tmpl){ + tmplRoot = parseTemplate(new TemplateNode(), tmpl, new MutableInt(), null); + } + private TemplateNode parseTemplate(TemplateNode root, String tmpl, MutableInt m, String parentTag){ + StringBuilder data = new StringBuilder(); + boolean tagOpen = false; + + for(; m.i 0) // Still some text left, add to node + root.add(new TemplateStaticString(data.toString())); + + // If we get to this point means that this node is incorrectly close + // or this is the end of the file, so we convert it to a normal node + if(parentTag != null) { + root = new TemplateNode(root); + String tagName = "{{"+parentTag+"}}"; + log.severe("Missing closure of tag: " + tagName); + root.addFirst(new TemplateStaticString(tagName)); + } + return root; + } + + + /**************************** Template Helper Classes *************************************/ + + protected interface TemplateEntity { + public void compile(StringBuilder str); + } + + protected class TemplateNode implements TemplateEntity { + private List entities; + + public TemplateNode(){ + this.entities = new ArrayList(); + } + public TemplateNode(TemplateNode node){ + this.entities = node.entities; + } + + public void addFirst(TemplateEntity s){ + entities.add(0, s); + } + public void add(TemplateEntity s){ + entities.add(s); + } + + public void compile(StringBuilder str) { + for(TemplateEntity sec : entities) + sec.compile(str); + } + } + + protected class TemplateCondition extends TemplateNode { + private TemplateDataAttribute attrib; + + public TemplateCondition(String key){ + this.attrib = new TemplateDataAttribute(key); + } + + public void compile(StringBuilder str) { + Object obj = attrib.getObject(); + if(obj != null) { + if(obj instanceof Boolean){ + if ((Boolean) obj) + super.compile(str); + } + else if(obj instanceof Short){ + if ((Short) obj != 0) + super.compile(str); + } + else if(obj instanceof Integer){ + if ((Integer) obj != 0) + super.compile(str); + } + else if(obj instanceof Long){ + if ((Long) obj != 0l) + super.compile(str); + } + else if(obj instanceof Float){ + if ((Float) obj != 0f) + super.compile(str); + } + else if(obj instanceof Double){ + if ((Double) obj != 0d) + super.compile(str); + } + else if(obj instanceof Iterable || obj.getClass().isArray()) { + Object prevObj = get("."); + set(".", obj); + + if (obj instanceof Iterable) { + for (Object o : (Iterable) obj) { // Iterate through the whole list + set(".", o); + super.compile(str); + } + } else if (obj.getClass().isArray()) { + int length = Array.getLength(obj); + for (int i = 0; i < length; i++) { + set(".", Array.get(obj, i)); + super.compile(str); + } + } + + // Reset map to parent object + if(prevObj != null) + set(".", prevObj); + else + remove("."); + } + else + super.compile(str); + + } + } + } + + protected class TemplateNegativeCondition extends TemplateNode { + private TemplateDataAttribute attrib; + + public TemplateNegativeCondition(String key){ + this.attrib = new TemplateDataAttribute(key); + } + + public void compile(StringBuilder str) { + Object obj = attrib.getObject(); + if(obj == null) + super.compile(str); + else { + if(obj instanceof Boolean) { + if ( ! (Boolean) obj) + super.compile(str); + } + else if(obj instanceof Integer){ + if ((Integer) obj == 0) + super.compile(str); + } + else if(obj instanceof Collection) { + if (((Collection) obj).isEmpty()) + super.compile(str); + } + else if(obj.getClass().isArray()) { + if (((Object[]) obj).length <= 0) + super.compile(str); + } + } + } + } + + protected class TemplateStaticString implements TemplateEntity { + private String text; + + public TemplateStaticString(String text){ + this.text = text; + } + + public void compile(StringBuilder str) { + str.append(text); + } + } + + protected class TemplateDataAttribute implements TemplateEntity { + private String tag; + private String[] keys; + + public TemplateDataAttribute(String tag){ + this.tag = tag; + this.keys = tag.trim().split("\\."); + if(this.keys.length == 0) + this.keys = new String[]{"."}; + if(this.keys[0].isEmpty()) // if tag starts with "." + this.keys[0] = "."; + } + + + public Object getObject(){ + if (data.containsKey(tag)) + return data.get(tag); + else if (data.containsKey(keys[0]) && data.get(keys[0]) != null) { + Object obj = data.get(keys[0]); + for(int i=1; i 2) { + String funcName = attrib.substring(0, attrib.length()-2); + // Using a loop as the direct lookup throws a exception if no field was found + // So this is probably a bit faster + for (Method m : obj.getClass().getMethods()) { + if (m.getParameterTypes().length == 0 && m.getName().equals(funcName)) { + m.setAccessible(true); + return m.invoke(obj); + } + } + } + } + else if(obj.getClass().isArray() && "length".equals(attrib)) + return Array.getLength(obj); + else if(obj instanceof Collection && "length".equals(attrib)) + return ((Collection) obj).size(); + else { + // Using a loop as the direct lookup throws a exception if no field was found + // So this is probably a bit faster + for (Field field : obj.getClass().getFields()) { // Only look for public fields + if (field.getName().equals(attrib)) { + field.setAccessible(true); + return field.get(obj); + } + } + } + }catch (IllegalAccessException e){ + log.log(Level.WARNING, null, e); + } catch (InvocationTargetException e) { + log.log(Level.WARNING, null, e); + } + return null; + } + + + public void compile(StringBuilder str) { + Object obj = getObject(); + if(obj != null) + if(obj instanceof Templator) + str.append(((Templator) obj).compile()); + else + str.append(obj.toString()); + else + str.append("null"); + } + } +} diff --git a/src/zutil/parser/URLDecoder.java b/src/zutil/parser/URLDecoder.java new file mode 100755 index 00000000..dc20564f --- /dev/null +++ b/src/zutil/parser/URLDecoder.java @@ -0,0 +1,77 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import zutil.converter.Converter; + +import java.io.UnsupportedEncodingException; + +/** + * This utility class will decode Strings encoded with % sign's to a normal String + * + * Created by Ziver on 2015-12-11. + */ +public class URLDecoder { + + public static String decode(String url){ + if(url == null) + return null; + + try { + StringBuilder out = new StringBuilder(); + byte[] buffer = null; + for (int i=0; i { + private static final HashMap> cache = new HashMap<>(); + + private int index; + private int length; + private Field field; + + + protected static List getStructFieldList(Class clazz){ + if (!cache.containsKey(clazz)) { + ArrayList list = new ArrayList<>(); + for (Field field : clazz.getFields()) { + if (field.isAnnotationPresent(BinaryField.class)) + list.add(new BinaryFieldData(field)); + } + Collections.sort(list); + cache.put(clazz, list); + } + return cache.get(clazz); + } + + + private BinaryFieldData(Field f){ + field = f; + BinaryField fieldData = field.getAnnotation(BinaryField.class); + index = fieldData.index(); + length = fieldData.length(); + } + + protected void setValue(Object obj, byte[] data){ + try { + field.setAccessible(true); + if (field.getType() == Boolean.class || field.getType() == boolean.class) + field.set(obj, data[0] != 0); + else if (field.getType() == Integer.class || field.getType() == int.class) + field.set(obj, Converter.toInt(data)); + else if (field.getType() == String.class) + field.set(obj, new String(data)); + } catch (IllegalAccessException e){ + e.printStackTrace(); + } + } + + // TODO: variable length support + protected byte[] getValue(Object obj){ + try { + if (field.getType() == Boolean.class || field.getType() == boolean.class) + return new byte[]{ (byte)(field.getBoolean(obj) ? 0x01 : 0x00) }; + else if (field.getType() == Integer.class || field.getType() == int.class) + return Converter.toBytes(field.getInt(obj)); + else if (field.getType() == String.class) + return ((String)(field.get(obj))).getBytes(); + } catch (IllegalAccessException e){ + e.printStackTrace(); + } + return null; + } + + + public int getBitLength(){ + return length; + } + + @Override + public int compareTo(BinaryFieldData o) { + return this.index - o.index; + } +} \ No newline at end of file diff --git a/src/zutil/parser/binary/BinaryStruct.java b/src/zutil/parser/binary/BinaryStruct.java new file mode 100755 index 00000000..bb4c9424 --- /dev/null +++ b/src/zutil/parser/binary/BinaryStruct.java @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.binary; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by ezivkoc on 2016-01-28. + */ +public interface BinaryStruct { + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + @interface BinaryField{ + int index(); + int length(); + } +} diff --git a/src/zutil/parser/binary/BinaryStructInputStream.java b/src/zutil/parser/binary/BinaryStructInputStream.java new file mode 100755 index 00000000..25940859 --- /dev/null +++ b/src/zutil/parser/binary/BinaryStructInputStream.java @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.binary; + +import zutil.ByteUtil; +import zutil.converter.Converter; +import zutil.parser.binary.BinaryStruct.BinaryField; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +/** + * A stream class that parses a byte stream into + * binary struct objects. + * + * @author Ziver + */ +public class BinaryStructInputStream { + + public static int parse(BinaryStruct struct, byte[] data) { + List structDataList = BinaryFieldData.getStructFieldList(struct.getClass()); + int bitOffset = 0; + for (BinaryFieldData field : structDataList){ + + int byteIndex = bitOffset / 8; + int bitIndex = 7 - bitOffset % 8; + int bitLength = Math.min(bitIndex+1, field.getBitLength()); + + int readLength = 0; + byte[] valueData = new byte[(int) Math.ceil(field.getBitLength() / 8.0)]; + for (int index = 0; index < valueData.length; ++index) { + valueData[index] = ByteUtil.getShiftedBits(data[byteIndex], bitIndex, bitLength); + readLength += bitLength; + byteIndex++; + bitIndex = 7; + bitLength = Math.min(bitIndex+1, field.getBitLength() - readLength); + } + field.setValue(struct, valueData); + bitOffset += field.getBitLength(); + } + return bitOffset; + } + + + + +} diff --git a/src/zutil/parser/binary/BinaryStructOutputStream.java b/src/zutil/parser/binary/BinaryStructOutputStream.java new file mode 100755 index 00000000..307addff --- /dev/null +++ b/src/zutil/parser/binary/BinaryStructOutputStream.java @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.binary; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + + +/** + * A stream class that generates a byte stream from + * binary struct objects. + * + * @author Ziver + */ +public class BinaryStructOutputStream { + + private OutputStream out; + private byte rest; + private int restLength; + + + public BinaryStructOutputStream(OutputStream out){ + this.out = out; + + rest = 0; + restLength = 0; + } + + + /** + * Generate a binary byte array from the provided struct. + * The byte array will be left + */ +/* public byte[] serialize(BinaryStruct struct) { + + }*/ + + /** + * Generate a binary stream from the provided struct and + * write the data to the underlying stream. + */ + public void write(BinaryStruct struct) throws IOException { + List structDataList = BinaryFieldData.getStructFieldList(struct.getClass()); + + for (BinaryFieldData field : structDataList){ + byte[] data = field.getValue(struct); + + for (int i=data.length-1; i>=0; --i) { + out.write(data[i]); + } + } + } + + + /** + * Writes any outstanding data to the stream + */ + public void flush() throws IOException { + if(restLength > 0){ + out.write(0xFF & rest); + rest = 0; + restLength = 0; + } + out.flush(); + } + + /** + * Flushes and closes the underlying stream + */ + public void close() throws IOException { + flush(); + out.close(); + } +} diff --git a/src/zutil/parser/json/JSONObjectInputStream.java b/src/zutil/parser/json/JSONObjectInputStream.java new file mode 100755 index 00000000..85e7b627 --- /dev/null +++ b/src/zutil/parser/json/JSONObjectInputStream.java @@ -0,0 +1,300 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.json; + +import zutil.ClassUtil; +import zutil.log.LogUtil; +import zutil.parser.Base64Decoder; +import zutil.parser.DataNode; + +import javax.activation.UnsupportedDataTypeException; +import java.io.*; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + + +public class JSONObjectInputStream extends InputStream implements ObjectInput, Closeable{ + private static final Logger logger = LogUtil.getLogger(); + protected static final String MD_OBJECT_ID = "@object_id"; + protected static final String MD_CLASS = "@class"; + + private JSONParser parser; + private HashMap registeredClasses; + private HashMap objectCache; + + + private JSONObjectInputStream() { + this.registeredClasses = new HashMap<>(); + this.objectCache = new HashMap<>(); + } + public JSONObjectInputStream(Reader in) { + this(); + this.parser = new JSONParser(in); + } + public JSONObjectInputStream(InputStream in) { + this(); + this.parser = new JSONParser(in); + } + + + /** + * If no metadata is available in the stream then this + * class will be instantiated and assigned data from the received JSON. + * + * @param c the Class that will be instantiated for the root JSON. + */ + public void registerRootClass(Class c){ + registeredClasses.put(null, c); + } + + /** + * A object instance of the given class will be created if the specific key is seen. + * This can be used for streams that do not have any class metadata. + * NOTE: any meta-data in the stream will override the registered classes. + * + * @param key a String key that will be looked for in the InputStream + * @param c the Class that will be instantiated for the specific key. + */ + public void registerClass(String key, Class c){ + registeredClasses.put(key, c); + } + + + /** + * @return the object read from the stream + */ + @Override + public Object readObject() throws IOException { + return readObject(null); + } + /** + * @param is a simple cast to this type + * @return the object read from the stream + */ + public T readGenericObject() throws IOException { + return readObject(null); + } + /** + * @param c will override the registered root class and use this value instead + * @param + * @return the object read from the stream + */ + public synchronized T readObject(Class c) throws IOException { + try{ + DataNode root = parser.read(); + if(root != null){ + return (T)readObject(c, null, root); + } + } catch (ClassNotFoundException e) { + logger.log(Level.WARNING, null, e); + } catch (NoSuchFieldException e) { + logger.log(Level.WARNING, null, e); + } catch (InstantiationException e) { + logger.log(Level.WARNING, null, e); + } catch (IllegalAccessException e) { + logger.log(Level.WARNING, null, e); + } finally { + objectCache.clear(); + } + return null; + } + + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected Object readType(Class type, Class[] genType, String key, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedDataTypeException, NoSuchFieldException { + if(json == null || type == null) + return null; + // Field type is a primitive? + if(type.isPrimitive() || String.class.isAssignableFrom(type)){ + return readPrimitive(type, json); + } + else if(type.isArray()){ + if(type.getComponentType() == byte.class) + return Base64Decoder.decodeToByte(json.getString()); + else{ + Object array = Array.newInstance(type.getComponentType(), json.size()); + for(int i=0; i=1? genType[0] : null), null, key, json.get(i))); + } + return list; + } + else if(Map.class.isAssignableFrom(type)){ + if(genType == null || genType.length < 2) + genType = ClassUtil.getGenericClasses(type, Map.class); + Map map = (Map)type.newInstance(); + for(Iterator it=json.keyIterator(); it.hasNext();){ + String subKey = it.next(); + if(json.get(subKey) != null) { + map.put( + subKey, + readType((genType.length >= 2 ? genType[1] : null), null, subKey, json.get(subKey))); + } + } + return map; + } + // Field is a new Object + else{ + return readObject(type, key, json); + } + } + + + protected Object readObject(Class type, String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, UnsupportedDataTypeException, NoSuchFieldException { + // Only parse if json is a map + if(json == null || !json.isMap()) + return null; + // See if the Object id is in the cache before continuing + if(json.getString("@object_id") != null && objectCache.containsKey(json.getInt(MD_OBJECT_ID))) + return objectCache.get(json.getInt(MD_OBJECT_ID)); + + // Resolve the class + Object obj = null; + // Try using explicit class + if(type != null){ + obj = type.newInstance(); + } + // Try using metadata + else if(json.getString(MD_CLASS) != null) { + Class objClass = Class.forName(json.getString(MD_CLASS)); + obj = objClass.newInstance(); + } + // Search for registered classes + else if(registeredClasses.containsKey(key)){ + Class objClass = registeredClasses.get(key); + obj = objClass.newInstance(); + } + // Unknown class + else { + logger.warning("Unknown type for key: '"+key+"'"); + return null; + } + + // Read all fields from the new object instance + for(Field field : obj.getClass().getDeclaredFields()){ + if((field.getModifiers() & Modifier.STATIC) == 0 && + (field.getModifiers() & Modifier.TRANSIENT) == 0 && + json.get(field.getName()) != null){ + // Parse field + field.setAccessible(true); + field.set(obj, + readType( + field.getType(), + ClassUtil.getGenericClasses(field), + field.getName(), + json.get(field.getName()))); + } + } + // Add object to the cache + if(json.getString(MD_OBJECT_ID) != null) + objectCache.put(json.getInt(MD_OBJECT_ID), obj); + return obj; + } + + + protected static Object readPrimitive(Class type, DataNode json){ + if (type == int.class || + type == Integer.class) return json.getInt(); + else if(type == long.class || + type == Long.class) return json.getLong(); + + else if(type == double.class || + type == Double.class) return json.getDouble(); + + else if(type == boolean.class || + type == Boolean.class) return json.getBoolean(); + else if(type == String.class) return json.getString(); + return null; + } + + + + + @Override public void readFully(byte[] b) throws IOException { + throw new UnsupportedOperationException (); + } + @Override public void readFully(byte[] b, int off, int len) throws IOException { + throw new UnsupportedOperationException (); + } + @Override public int skipBytes(int n) throws IOException { + throw new UnsupportedOperationException (); + } + @Override public boolean readBoolean() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public byte readByte() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public int readUnsignedByte() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public short readShort() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public int readUnsignedShort() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public char readChar() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public int readInt() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public long readLong() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public float readFloat() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public double readDouble() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public String readLine() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public String readUTF() throws IOException { + throw new UnsupportedOperationException (); + } + @Override public int read() throws IOException { + throw new UnsupportedOperationException (); + } + +} diff --git a/src/zutil/parser/json/JSONObjectOutputStream.java b/src/zutil/parser/json/JSONObjectOutputStream.java new file mode 100755 index 00000000..5033a9fb --- /dev/null +++ b/src/zutil/parser/json/JSONObjectOutputStream.java @@ -0,0 +1,247 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.json; + +import zutil.ClassUtil; +import zutil.parser.Base64Encoder; +import zutil.parser.DataNode; +import zutil.parser.DataNode.DataType; + +import javax.activation.UnsupportedDataTypeException; +import java.io.*; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static zutil.parser.json.JSONObjectInputStream.MD_CLASS; +import static zutil.parser.json.JSONObjectInputStream.MD_OBJECT_ID; + +public class JSONObjectOutputStream extends OutputStream implements ObjectOutput, Closeable{ + /** If the generated JSON should contain class def meta-data **/ + private boolean generateMetaData = true; + /** If fields that are null should be included in the json **/ + private boolean ignoreNullFields = true; + + /** Cache of parsed objects **/ + private HashMap objectCache; + private JSONWriter out; + + private JSONObjectOutputStream() { + this.objectCache = new HashMap(); + } + public JSONObjectOutputStream(OutputStream out) { + this(); + this.out = new JSONWriter(out); + } + public JSONObjectOutputStream(Writer out) { + this(); + this.out = new JSONWriter(out); + } + + + + public synchronized void writeObject(Object obj) throws IOException{ + try{ + out.write(getDataNode(obj)); + } catch (IllegalAccessException e) { + throw new IOException("Unable to serialize object", e); + } finally { + objectCache.clear(); + } + } + + protected DataNode getDataNode(Object obj) throws IOException, IllegalArgumentException, IllegalAccessException { + if(obj == null) + return null; + Class objClass = obj.getClass(); + DataNode root; + + // Check if the object is a primitive + if(ClassUtil.isPrimitive(obj.getClass()) || + ClassUtil.isWrapper(obj.getClass())){ + root = getPrimitiveDataNode(obj.getClass(), obj); + } + // Add an array + else if(objClass.isArray()){ + // Special case for byte arrays + if(objClass.getComponentType() == byte.class) { + root = new DataNode(DataType.String); + root.set(Base64Encoder.encode((byte[])obj)); + } + // Other arrays + else { + root = new DataNode(DataType.List); + for (int i = 0; i < Array.getLength(obj); i++) { + root.add(getDataNode(Array.get(obj, i))); + } + } + } + // List + else if(List.class.isAssignableFrom(objClass)){ + root = new DataNode(DataNode.DataType.List); + List list = (List)obj; + for(Object item : list){ + root.add(getDataNode(item)); + } + } + // Map + else if(Map.class.isAssignableFrom(objClass)){ + root = new DataNode(DataNode.DataType.Map); + Map map = (Map)obj; + for(Object key : map.keySet()){ + root.set( + getDataNode(key).getString(), + getDataNode(map.get(key))); + } + } + // Object is a complex data type + else { + root = new DataNode(DataNode.DataType.Map); + // Generate meta data + if(generateMetaData){ + // Cache + if(objectCache.containsKey(obj)){ // Hit + root.set(MD_OBJECT_ID, objectCache.get(obj)); + return root; + } + else{ // Miss + objectCache.put(obj, objectCache.size()+1); + root.set(MD_OBJECT_ID, objectCache.size()); + } + root.set(MD_CLASS, obj.getClass().getName()); + } + // Add all the fields to the DataNode + for(Field field : obj.getClass().getDeclaredFields()){ + if((field.getModifiers() & Modifier.STATIC) == 0 && + (field.getModifiers() & Modifier.TRANSIENT) == 0){ + field.setAccessible(true); + Object fieldObj = field.get(obj); + + // has object a value? + if(ignoreNullFields && fieldObj == null) + continue; + else + root.set(field.getName(), getDataNode(fieldObj)); + } + } + } + return root; + } + + private DataNode getPrimitiveDataNode(Class type, Object value) throws UnsupportedDataTypeException, IllegalArgumentException, IllegalAccessException { + DataNode node = null; + if (type == int.class || + type == Integer.class || + type == long.class || + type == Long.class || + type == double.class || + type == Double.class) + node = new DataNode(DataType.Number); + + else if(type == boolean.class || + type == Boolean.class) + node = new DataNode(DataType.Boolean); + + else if(type == String.class || + type == char.class || + type == Character.class) + node = new DataNode(DataType.String); + else + throw new UnsupportedDataTypeException("Unsupported primitive data type: "+type.getName()); + + if(value != null) + node.set(value.toString()); + return node; + } + + /** + * Enable or disables the use of meta data in the JSON + * stream for class definitions and caching. + * If meta data is disabled then all parsed classes need to + * be registered in JSONObjectInputStream to be able to decode objects. + * + * All the meta-data tags will start with a '@' + */ + public void enableMetaData(boolean generate){ + generateMetaData = generate; + } + + /** + * Defines if null fields in objects should be included + * in the JSON output. Default value is true + */ + public void ignoreNullFields(boolean enable) { + ignoreNullFields = enable; + } + + public void flush() throws IOException { + super.flush(); + out.flush(); + } + + + + @Override public void writeBoolean(boolean v) throws IOException { + out.write(new DataNode(v)); + } + @Override public void writeByte(int v) throws IOException { + throw new UnsupportedOperationException (); + } + @Override public void writeShort(int v) throws IOException { + out.write(new DataNode(v)); + } + @Override public void writeChar(int v) throws IOException { + out.write(new DataNode((char)v)); + } + @Override public void writeInt(int v) throws IOException { + out.write(new DataNode(v)); + } + @Override public void writeLong(long v) throws IOException { + out.write(new DataNode(v)); + } + @Override public void writeFloat(float v) throws IOException { + out.write(new DataNode(v)); + } + @Override public void writeDouble(double v) throws IOException { + out.write(new DataNode(v)); + } + @Override public void writeBytes(String s) throws IOException { + throw new UnsupportedOperationException (); + } + @Override public void writeChars(String s) throws IOException { + out.write(new DataNode(s)); + } + @Override public void write(int b) throws IOException { + out.write(new DataNode(b)); + } + @Override public void writeUTF(String s) throws IOException { + out.write(new DataNode(s)); + } + + +} diff --git a/src/zutil/parser/json/JSONParser.java b/src/zutil/parser/json/JSONParser.java new file mode 100755 index 00000000..9e51780b --- /dev/null +++ b/src/zutil/parser/json/JSONParser.java @@ -0,0 +1,175 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.json; + +import zutil.parser.DataNode; +import zutil.parser.DataNode.DataType; +import zutil.parser.Parser; +import zutil.struct.MutableInt; + +import java.io.*; +import java.util.regex.Pattern; + +/** + * This is a JSON parser class + * + * @author Ziver + */ +public class JSONParser extends Parser { + // Values for MutableInt + private static final int CONTINUE = 0; + private static final int END_WITH_NULL = 1; + private static final int END_WITH_VALUE = 2; + // Regex for parsing primitives + private static final Pattern NUMBER_PATTERN = Pattern.compile("^[0-9.]++$"); + private static final Pattern BOOLEAN_PATTERN = Pattern.compile("^(true|false)$", Pattern.CASE_INSENSITIVE); + private static final Pattern NULL_PATTERN = Pattern.compile("^null$", Pattern.CASE_INSENSITIVE); + + private Reader in; + + + public JSONParser(Reader in){ + this.in = in; + } + public JSONParser(InputStream in){ + this.in = new InputStreamReader(in); + } + + /** + * Starts parsing from the input. + * This method will block until one root tree has been parsed. + * + * @return a DataNode object representing the input JSON + */ + @Override + public DataNode read() throws IOException { + return parse(in, new MutableInt()); + } + + /** + * Starts parsing from a string + * + * @param json is the JSON String to parse + * @return a DataNode object representing the JSON in the input String + */ + public static DataNode read(String json){ + try{ + return parse(new StringReader(json), new MutableInt()); + }catch (IOException e){ + e.printStackTrace(); + }catch (NullPointerException e){} + return null; + } + + /** + * This is the real recursive parsing method + */ + protected static DataNode parse(Reader in, MutableInt end) throws IOException { + DataNode root = null; + DataNode key = null; + DataNode node = null; + end.i = CONTINUE; + + int c = '_'; + while((c=in.read()) >= 0 && + (Character.isWhitespace(c) || c == ',' || c == ':')); + + switch( c ){ + // End of stream + case -1: + // This is the end of an Map or List + case ']': + case '}': + case (char)-1: + end.i = END_WITH_NULL; + return null; + // Parse Map + case '{': + root = new DataNode(DataType.Map); + while(end.i == CONTINUE) { + key = parse(in, end); + if(end.i == END_WITH_NULL) // Break if there is no more data + break; + node = parse(in, end); + if(end.i != END_WITH_NULL) // Only add the entry if it is a value + root.set( key.toString(), node ); + } + end.i = CONTINUE; + break; + // Parse List + case '[': + root = new DataNode(DataType.List); + while(end.i == CONTINUE){ + node = parse(in, end); + if(end.i != END_WITH_NULL) + root.add( node ); + } + end.i = CONTINUE; + break; + // Parse String + // TODO: Support double backslash escaping + case '\"': + root = new DataNode(DataType.String); + StringBuilder str = new StringBuilder(); + while((c=in.read()) >= 0 && c != '\"') + str.append((char)c); + root.set(str.toString()); + break; + // Parse unknown type + default: + StringBuilder tmp = new StringBuilder().append((char)c); + while((c=in.read()) >= 0 && c != ',' && c != ':'){ + if(c == ']' || c == '}'){ + end.i = END_WITH_VALUE; + break; + } + tmp.append((char)c); + } + // Check what type of type the data is + String data = tmp.toString().trim(); + if( NULL_PATTERN.matcher(data).matches() ) + root = null; + else if( BOOLEAN_PATTERN.matcher(data).matches() ) + root = new DataNode(DataType.Boolean); + else if( NUMBER_PATTERN.matcher(data).matches() ) + root = new DataNode(DataType.Number); + else { + root = new DataNode(DataType.String); + data = unEscapeString(data); + } + if(root != null) + root.set(data); + break; + } + + return root; + } + + private static String unEscapeString(String str){ + // Replace two backslash with one + return str.replaceAll("\\\\\\\\", "\\\\"); + } + +} diff --git a/src/zutil/parser/json/JSONWriter.java b/src/zutil/parser/json/JSONWriter.java new file mode 100755 index 00000000..6e00f98f --- /dev/null +++ b/src/zutil/parser/json/JSONWriter.java @@ -0,0 +1,149 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.json; + +import zutil.io.StringOutputStream; +import zutil.parser.DataNode; +import zutil.parser.DataNode.DataType; + +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Iterator; + +/** + * Writes An JSONNode to an String or stream + * + * @author Ziver + */ +public class JSONWriter{ + private PrintWriter out; + + /** + * Creates a new instance of the writer + * + * @param out the OutputStream that the Nodes will be sent to + */ + public JSONWriter(OutputStream out){ + this( new PrintWriter(out) ); + } + + /** + * Creates a new instance of the writer + * + * @param out the OutputStream that the Nodes will be sent to + */ + public JSONWriter(Writer out){ + this( new PrintWriter(out) ); + } + + /** + * Creates a new instance of the writer + * + * @param out the OutputStream that the Nodes will be sent to + */ + public JSONWriter(PrintWriter out){ + this.out = out; + } + + /** + * Writes the specified node to the stream + * + * @param root is the root node + */ + public void write(DataNode root){ + if(root == null){ + out.print("null"); + return; + } + + boolean first = true; + switch(root.getType()){ + // Write Map + case Map: + out.append('{'); + Iterator it = root.keyIterator(); + while(it.hasNext()){ + if(!first) + out.append(", "); + String key = it.next(); + out.append('\"'); + out.append(escapeString(key)); + out.append("\": "); + write(root.get(key)); + first = false; + } + out.append('}'); + break; + // Write List + case List: + out.append('['); + for(DataNode node : root){ + if(!first) + out.append(", "); + write(node); + first = false; + } + out.append(']'); + break; + default: + if(root.getString() != null && root.getType() == DataType.String){ + out.append('\"'); + out.append(escapeString(root.toString())); + out.append('\"'); + } else + out.append(root.toString()); + break; + } + } + + private static String escapeString(String str){ + // Replace one backslash with two + return str.replaceAll("\\\\", "\\\\\\\\"); + } + + /** + * Closes the internal stream + */ + public void close(){ + out.close(); + } + + /** + * @return JSON String that is generated from the input DataNode graph + */ + public static String toString(DataNode root){ + StringOutputStream out = new StringOutputStream(); + JSONWriter writer = new JSONWriter(out); + writer.write(root); + writer.close(); + return out.toString(); + } + + public void flush(){ + out.print("\n"); + out.flush(); + } +} diff --git a/plugins/hal-powerchallenge/src/se/hal/plugin/powerchallenge/page/PCHeatMapWebPage.java b/src/zutil/parser/wsdl/WSDLHttpPage.java old mode 100644 new mode 100755 similarity index 59% rename from plugins/hal-powerchallenge/src/se/hal/plugin/powerchallenge/page/PCHeatMapWebPage.java rename to src/zutil/parser/wsdl/WSDLHttpPage.java index f73a2ab4..bc77dd17 --- a/plugins/hal-powerchallenge/src/se/hal/plugin/powerchallenge/page/PCHeatMapWebPage.java +++ b/src/zutil/parser/wsdl/WSDLHttpPage.java @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Ziver Koc + * Copyright (c) 2015 Ziver Koc * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,33 +22,33 @@ * THE SOFTWARE. */ -package se.hal.plugin.powerchallenge.page; +package zutil.parser.wsdl; -import se.hal.HalContext; -import se.hal.intf.HalWebPage; -import zutil.io.file.FileUtil; -import zutil.parser.Templator; +import zutil.net.http.HttpHeader; +import zutil.net.http.HttpPage; +import zutil.net.http.HttpPrintStream; +import zutil.net.ws.WebServiceDef; +import java.io.IOException; import java.util.Map; -public class PCHeatMapWebPage extends HalWebPage { - private static final String TEMPLATE = HalContext.RESOURCE_ROOT + "/web/pc_heatmap.tmpl"; +/** + * User: Ziver + */ +public class WSDLHttpPage implements HttpPage { + /** The WSDL document **/ + private WSDLWriter wsdl; - - public PCHeatMapWebPage() { - super("pc_heatmap"); - super.getRootNav().createSubNav("Sensors").createSubNav(this.getId(), "Heatmap").setWeight(60); + public WSDLHttpPage( WebServiceDef wsDef ){ + wsdl = new WSDLWriter( wsDef ); } - @Override - public Templator httpRespond( - Map session, - Map cookie, - Map request) - throws Exception{ - - Templator tmpl = new Templator(FileUtil.find(TEMPLATE)); - return tmpl; + public void respond(HttpPrintStream out, + HttpHeader headers, + Map session, + Map cookie, + Map request) throws IOException{ + out.setHeader("Content-Type", "text/xml"); + wsdl.write( out ); } - } diff --git a/src/zutil/parser/wsdl/WSDLService.java b/src/zutil/parser/wsdl/WSDLService.java new file mode 100644 index 00000000..1960445b --- /dev/null +++ b/src/zutil/parser/wsdl/WSDLService.java @@ -0,0 +1,52 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.wsdl; + +import org.dom4j.Element; +import zutil.net.ws.WSMethodDef; + +/** + * This interface defines a WSDL Service type. + * + * User: Ziver + */ +public abstract class WSDLService { + /** The URL of this service **/ + private String url; + + public WSDLService(String url){ + this.url = url; + } + + public String getServiceAddress(){ + return url; + } + + public abstract String getServiceType(); + + public abstract void generateBinding(Element definitions); + + public abstract void generateOperation(Element definitions, WSMethodDef method); +} diff --git a/src/zutil/parser/wsdl/WSDLServiceSOAP.java b/src/zutil/parser/wsdl/WSDLServiceSOAP.java new file mode 100644 index 00000000..75631599 --- /dev/null +++ b/src/zutil/parser/wsdl/WSDLServiceSOAP.java @@ -0,0 +1,78 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.wsdl; + +import org.dom4j.Element; +import zutil.net.ws.WSMethodDef; + +/** + * User: Ziver + */ +public class WSDLServiceSOAP extends WSDLService{ + + public WSDLServiceSOAP(String url){ + super(url); + } + + @Override + public String getServiceType() { return "soap"; } + + @Override + public void generateBinding(Element definitions) { + // definitions -> binding -> soap:binding + Element soap_binding = definitions.addElement("soap:binding"); + soap_binding.addAttribute("style", "rpc"); + soap_binding.addAttribute("transport", "http://schemas.xmlsoap.org/soap/http"); + } + + @Override + public void generateOperation(Element definitions, WSMethodDef method) { + // definitions -> binding -> operation + Element operation = definitions.addElement("wsdl:operation"); + operation.addAttribute("name", method.getName()); + + // definitions -> binding -> operation -> soap:operation + Element soap_operation = operation.addElement("soap:operation"); + soap_operation.addAttribute("soapAction", method.getNamespace()); + + //*************************** Input + // definitions -> binding -> operation -> input + Element input = operation.addElement("wsdl:input"); + // definitions -> binding -> operation -> input -> body + Element input_body = input.addElement("soap:body"); + input_body.addAttribute("use", "literal"); + input_body.addAttribute("namespace", method.getNamespace()); + + //*************************** output + if( method.getOutputCount() > 0 ){ + // definitions -> binding -> operation -> output + Element output = operation.addElement("wsdl:output"); + // definitions -> binding -> operation -> input -> body + Element output_body = output.addElement("soap:body"); + output_body.addAttribute("use", "literal"); + output_body.addAttribute("namespace", method.getNamespace()); + } + } +} diff --git a/src/zutil/parser/wsdl/WSDLWriter.java b/src/zutil/parser/wsdl/WSDLWriter.java new file mode 100644 index 00000000..52102c37 --- /dev/null +++ b/src/zutil/parser/wsdl/WSDLWriter.java @@ -0,0 +1,394 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.wsdl; + +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; +import zutil.io.StringOutputStream; +import zutil.net.ws.WSMethodDef; +import zutil.net.ws.WSParameterDef; +import zutil.net.ws.WSReturnObject; +import zutil.net.ws.WSReturnObject.WSValueName; +import zutil.net.ws.WebServiceDef; + +import java.io.*; +import java.lang.reflect.Field; +import java.util.ArrayList; + +public class WSDLWriter{ + /** Current Web service definition ***/ + private WebServiceDef ws; + /** Cache of generated WSDL **/ + private String cache; + /** A list of services **/ + private ArrayList services; + + public WSDLWriter( WebServiceDef ws ){ + this.services = new ArrayList(); + this.ws = ws; + } + + /** + * Add a service to be published with the WSDL + */ + public void addService(WSDLService serv){ + cache = null; + services.add(serv); + } + + + public void write( Writer out ) throws IOException { + out.write(generate()); + } + public void write( PrintStream out ) { + out.print(generate()); + } + public void write( OutputStream out ) throws IOException { + out.write(generate().getBytes() ); + } + + + private String generate(){ + if(cache == null){ + try { + OutputFormat outformat = OutputFormat.createPrettyPrint(); + StringOutputStream out = new StringOutputStream(); + XMLWriter writer = new XMLWriter(out, outformat); + + Document docroot = generateDefinition(); + writer.write(docroot); + + writer.flush(); + this.cache = out.toString(); + out.close(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return cache; + } + + private Document generateDefinition(){ + Document wsdl = DocumentHelper.createDocument(); + Element definitions = wsdl.addElement("wsdl:definitions"); + definitions.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/"); + definitions.addNamespace("soap", "http://schemas.xmlsoap.org/wsdl/soap/"); + definitions.addNamespace("http", "http://schemas.xmlsoap.org/wsdl/http/"); + definitions.addNamespace("xsd", "http://www.w3.org/2001/XMLSchema"); + definitions.addNamespace("soap-enc", "http://schemas.xmlsoap.org/soap/encoding/"); + definitions.addNamespace("tns", ws.getNamespace()+"?type"); + definitions.addAttribute("targetNamespace", ws.getNamespace()); + + generateType(definitions); + generateMessages(definitions); + generatePortType(definitions); + generateBinding(definitions); + generateService(definitions); + + return wsdl; + } + + private void generateMessages(Element definitions){ + for( WSMethodDef method : ws.getMethods() ){ + generateMessage(definitions, method); + } + + // Default message used for functions without input parameters + // definitions -> message: empty + Element empty = definitions.addElement("wsdl:message"); + empty.addAttribute("name", "empty"); + // definitions -> message: empty -> part + Element empty_part = empty.addElement("wsdl:part"); + empty_part.addAttribute("name", "empty"); + empty_part.addAttribute("type", "td:empty"); + + // Exception message + // definitions -> message: exception + Element exception = definitions.addElement("wsdl:message"); + exception.addAttribute("name", "exception"); + // definitions -> message: exception -> part + Element exc_part = exception.addElement("wsdl:part"); + exc_part.addAttribute("name", "exception"); + exc_part.addAttribute("type", "td:string"); + } + + private void generateMessage(Element parent, WSMethodDef method){ + //*************************** Input + if( method.getInputCount() > 0 ){ + // definitions -> message + Element input = parent.addElement("wsdl:message"); + input.addAttribute("name", method.getName()+"Request"); + + // Parameters + for( WSParameterDef param : method.getInputs() ){ + // definitions -> message -> part + Element part = input.addElement("wsdl:part"); + part.addAttribute("name", param.getName()); + part.addAttribute("type", "xsd:"+getClassName( param.getParamClass())); + + if( param.isOptional() ) + part.addAttribute("minOccurs", "0"); + } + } + //*************************** Output + if( method.getOutputCount() > 0 ){ + // definitions -> message + Element output = parent.addElement("wsdl:message"); + output.addAttribute("name", method.getName()+"Response"); + + // Parameters + for( WSParameterDef param : method.getOutputs() ){ + // definitions -> message -> part + Element part = output.addElement("wsdl:part"); + part.addAttribute("name", param.getName()); + + Class paramClass = param.getParamClass(); + Class valueClass = getClass( paramClass ); + // is an binary array + if(byte[].class.isAssignableFrom( paramClass )){ + part.addAttribute("type", "xsd:base64Binary"); + } + // is an array? + else if( paramClass.isArray()){ + part.addAttribute("type", "td:" +getArrayClassName(paramClass)); + } + else if( WSReturnObject.class.isAssignableFrom(valueClass) ){ + // its an SOAPObject + part.addAttribute("type", "td:"+getClassName( paramClass )); + } + else{// its an Object + part.addAttribute("type", "xsd:"+getClassName( paramClass )); + } + } + } + } + + private void generatePortType(Element definitions){ + // definitions -> portType + Element portType = definitions.addElement("wsdl:portType"); + portType.addAttribute("name", ws.getName()+"PortType"); + + for( WSMethodDef method : ws.getMethods() ){ + // definitions -> portType -> operation + Element operation = portType.addElement("wsdl:operation"); + operation.addAttribute("name", method.getName()); + + // Documentation + if(method.getDocumentation() != null){ + Element doc = operation.addElement("wsdl:documentation"); + doc.setText(method.getDocumentation()); + } + + //*************************** Input + if( method.getInputCount() > 0 ){ + // definitions -> message + Element input = operation.addElement("wsdl:input"); + input.addAttribute("message", "tns:"+method.getName()+"Request"); + } + //*************************** Output + if( method.getOutputCount() > 0 ){ + // definitions -> message + Element output = operation.addElement("wsdl:output"); + output.addAttribute("message", "tns:"+method.getName()+"Response"); + } + //*************************** Fault + if( method.getOutputCount() > 0 ){ + // definitions -> message + Element fault = operation.addElement("wsdl:fault"); + fault.addAttribute("message", "tns:exception"); + } + } + } + + + private void generateBinding(Element definitions){ + // definitions -> binding + Element binding = definitions.addElement("wsdl:binding"); + binding.addAttribute("name", ws.getName()+"Binding"); + binding.addAttribute("type", "tns:"+ws.getName()+"PortType"); + + for(WSDLService serv : services){ + serv.generateBinding(binding); + + for(WSMethodDef method : ws.getMethods()){ + serv.generateOperation(binding, method); + } + } + } + + + private void generateService(Element parent){ + // definitions -> service + Element root = parent.addElement("wsdl:service"); + root.addAttribute("name", ws.getName()+"Service"); + + // definitions -> service -> port + Element port = root.addElement("wsdl:port"); + port.addAttribute("name", ws.getName()+"Port"); + port.addAttribute("binding", "tns:"+ws.getName()+"Binding"); + + for(WSDLService serv : services){ + // definitions -> service-> port -> address + Element address = port.addElement(serv.getServiceType()+":address"); + address.addAttribute("location", serv.getServiceAddress()); + } + } + + /** + * This function generates the Type section of the WSDL. + *
    +	 * -wsdl:definitions
    +	 *     -wsdl:type
    +	 *  
    + */ + private void generateType(Element definitions){ + ArrayList> types = new ArrayList>(); + // Find types + for( WSMethodDef method : ws.getMethods() ){ + if( method.getOutputCount() > 0 ){ + for( WSParameterDef param : method.getOutputs() ){ + Class paramClass = param.getParamClass(); + Class valueClass = getClass(paramClass); + // is an array? or special class + if( paramClass.isArray() || WSReturnObject.class.isAssignableFrom(valueClass)){ + // add to type generation list + if(!types.contains( paramClass )) + types.add( paramClass ); + } + } + } + } + + // definitions -> types + Element typeE = definitions.addElement("wsdl:types"); + Element schema = typeE.addElement("xsd:schema"); + schema.addAttribute("targetNamespace", ws.getNamespace()+"?type"); + + // empty type + Element empty = schema.addElement("xsd:complexType"); + empty.addAttribute("name", "empty"); + empty.addElement("xsd:sequence"); + + for(int n=0; n c = types.get(n); + // Generate Array type + if(c.isArray()){ + Class ctmp = getClass(c); + + Element type = schema.addElement("xsd:complexType"); + type.addAttribute("name", getArrayClassName(c)); + + Element sequence = type.addElement("xsd:sequence"); + + Element element = sequence.addElement("xsd:element"); + element.addAttribute("minOccurs", "0"); + element.addAttribute("maxOccurs", "unbounded"); + element.addAttribute("name", "element"); + element.addAttribute("nillable", "true"); + if( WSReturnObject.class.isAssignableFrom(ctmp) ) + element.addAttribute("type", "tns:"+getClassName(c).replace("[]", "")); + else + element.addAttribute("type", "xsd:"+getClassName(c).replace("[]", "")); + + if(!types.contains(ctmp)) + types.add(ctmp); + } + // Generate SOAPObject type + else if(WSReturnObject.class.isAssignableFrom(c)){ + Element type = schema.addElement("xsd:complexType"); + type.addAttribute("name", getClassName(c)); + + Element sequence = type.addElement("xsd:sequence"); + + Field[] fields = c.getFields(); + for(int i=0; i cTmp = getClass(fields[i].getType()); + if( WSReturnObject.class.isAssignableFrom(cTmp) ){ + element.addAttribute("type", "tns:"+getClassName(cTmp)); + if(!types.contains(cTmp)) + types.add(cTmp); + } + else{ + element.addAttribute("type", "xsd:"+getClassName(fields[i].getType())); + } + // Is the Field optional + if(tmp != null && tmp.optional()) + element.addAttribute("minOccurs", "0"); + } + } + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////////// + // TODO: FIX THESE ARE DUPLICATES FROM SOAPHttpPage + /////////////////////////////////////////////////////////////////////////////////////////////// + + private Class getClass(Class c){ + if(c!=null && c.isArray()){ + return getClass(c.getComponentType()); + } + return c; + } + + private String getArrayClassName(Class c){ + return "ArrayOf"+getClassName(c).replaceAll("[\\[\\]]", ""); + } + + private String getClassName(Class c){ + Class cTmp = getClass(c); + if( byte[].class.isAssignableFrom(c) ){ + return "base64Binary"; + } + else if( WSReturnObject.class.isAssignableFrom(cTmp) ){ + return c.getSimpleName(); + } + else{ + String ret = c.getSimpleName().toLowerCase(); + + if( cTmp == Integer.class ) ret = ret.replaceAll("integer", "int"); + else if( cTmp == Character.class ) ret = ret.replaceAll("character", "char"); + + return ret; + } + } + + public void close() {} + +} diff --git a/src/zutil/plugin/PluginData.java b/src/zutil/plugin/PluginData.java new file mode 100755 index 00000000..663babf7 --- /dev/null +++ b/src/zutil/plugin/PluginData.java @@ -0,0 +1,176 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.plugin; + +import zutil.log.LogUtil; +import zutil.parser.DataNode; + +import java.net.MalformedURLException; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class contains information about a plugin + * and implementation instances of the plugin interfaces + * + * @author Ziver + */ +public class PluginData { + private static Logger log = LogUtil.getLogger(); + + private double pluginVersion; + private String pluginName; + private HashMap, List>> classMap; + private HashMap objectMap; + + + protected PluginData(DataNode data) throws ClassNotFoundException, MalformedURLException { + classMap = new HashMap<>(); + objectMap = new HashMap(); + + pluginVersion = data.getDouble("version"); + pluginName = data.getString("name"); + log.fine("Plugin: " + this); + + DataNode node = data.get("interfaces"); + if(node.isMap()) + addInterfaces(node); + else if(node.isList()) { + Iterator intfs_it = node.iterator(); + while (intfs_it.hasNext()) { + addInterfaces(intfs_it.next()); + } + } + } + private void addInterfaces(DataNode node){ + Iterator intf_it = node.keyIterator(); + while (intf_it.hasNext()) { + String pluginIntf = intf_it.next(); + String className = node.get(pluginIntf).getString(); + + Class intfClass = getClassByName(pluginIntf); + Class pluginClass = getClassByName(className); + if (intfClass == null || pluginClass == null) + log.warning("Plugin interface: " + + (intfClass==null ? "(Not Available) " : "") + pluginIntf + " --> " + + (pluginClass==null ? "(Not Available) " : "") + className); + else + log.finer("Plugin interface: "+ pluginIntf +" --> "+ className); + + if (intfClass == null || pluginClass == null) + continue; + + if (!classMap.containsKey(intfClass)) + classMap.put(intfClass, new ArrayList>()); + classMap.get(intfClass).add(pluginClass); + } + } + private static Class getClassByName(String name) { + try { + return Class.forName(name); + }catch (Exception e){ + //log.log(Level.WARNING, null, e); // No need to log, we are handling it + } + return null; + } + + + public double getVersion(){ + return pluginVersion; + } + public String getName(){ + return pluginName; + } + + + public Iterator getObjectIterator(Class intf){ + if(!classMap.containsKey(intf)) + return Collections.emptyIterator(); + return new PluginObjectIterator(classMap.get(intf).iterator()); + } + public Iterator> getClassIterator(Class intf){ + if(!classMap.containsKey(intf)) + return Collections.emptyIterator(); + return classMap.get(intf).iterator(); + } + + private T getObject(Class objClass) { + try { + if (!objectMap.containsKey(objClass)) + objectMap.put(objClass, objClass.newInstance()); + return (T) objectMap.get(objClass); + } catch (Exception e) { + log.log(Level.WARNING, null, e); + } + return null; + } + + + public boolean contains(Class intf){ + return classMap.containsKey(intf); + } + + public String toString(){ + return getName()+"(ver: "+getVersion()+")"; + } + + + + private class PluginObjectIterator implements Iterator{ + private Iterator> classIt; + private T currentObj; + + public PluginObjectIterator(Iterator> it) { + classIt = it; + } + + @Override + public boolean hasNext() { + if(currentObj != null) + return true; + while (classIt.hasNext()){ + currentObj = (T)getObject(classIt.next()); + if(currentObj != null) + return true; + } + return false; + } + + @Override + public T next() { + if(!hasNext()) + throw new NoSuchElementException(); + T tmp = currentObj; + currentObj = null; + return tmp; + } + + @Override + public void remove() { + throw new RuntimeException("Iterator is ReadOnly"); + } + } +} diff --git a/src/zutil/plugin/PluginManager.java b/src/zutil/plugin/PluginManager.java new file mode 100755 index 00000000..027aa779 --- /dev/null +++ b/src/zutil/plugin/PluginManager.java @@ -0,0 +1,156 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.plugin; + +import zutil.io.IOUtil; +import zutil.io.file.FileSearcher; +import zutil.log.LogUtil; +import zutil.parser.DataNode; +import zutil.parser.json.JSONParser; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.logging.Logger; + +/** + * This class will search the file system for files + * with the name "plugin.json" that defines data + * parameters for a single plugin. + * The class will only load the latest version of the specific plugin. + * + * @author Ziver + */ +public class PluginManager implements Iterable{ + private static Logger log = LogUtil.getLogger(); + + private HashMap plugins; + + + public static PluginManager load(String path){ + return new PluginManager(path); + } + + public PluginManager(){ + this("./"); + } + public PluginManager(String path){ + plugins = new HashMap(); + + FileSearcher search = new FileSearcher(new File(path)); + search.setRecursive(true); + search.searchFolders(false); + search.searchCompressedFiles(true); + search.setFileName("plugin.json"); + + log.fine("Searching for plugins..."); + for(FileSearcher.FileSearchItem file : search){ + try { + DataNode node = JSONParser.read(IOUtil.getContentAsString(file.getInputStream())); + log.fine("Found plugin: "+file.getPath()); + PluginData plugin = new PluginData(node); + + if (!plugins.containsKey(plugin.getName())){ + plugins.put(plugin.getName(), plugin); + } + else { + double version = plugins.get(plugin.getName()).getVersion(); + if(version < plugin.getVersion()) + plugins.put(plugin.getName(), plugin); + else if(version == plugin.getVersion()) + log.fine("Ignoring duplicate plugin: " + plugin); + else + log.fine("Ignoring outdated plugin: "+plugin); + + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public Iterator iterator() { + return plugins.values().iterator(); + } + public Iterator getObjectIterator(Class intf) { + return new PluginInterfaceIterator(plugins.values().iterator(), intf); + } + + public ArrayList toArray() { + return toGenericArray(iterator()); + } + public ArrayList toArray(Class intf) { + return toGenericArray(getObjectIterator(intf)); + } + private ArrayList toGenericArray(Iterator it) { + ArrayList list = new ArrayList<>(); + while(it.hasNext()) + list.add(it.next()); + return list; + } + + + public static class PluginInterfaceIterator implements Iterator { + private Class intf; + private Iterator pluginIt; + private Iterator objectIt; + + PluginInterfaceIterator(Iterator it, Class intf){ + this.intf = intf; + this.pluginIt = it; + } + + @Override + public boolean hasNext() { + if(pluginIt == null) + return false; + if(objectIt != null && objectIt.hasNext()) + return true; + + while(pluginIt.hasNext()) { + objectIt = pluginIt.next().getObjectIterator(intf); + if(objectIt.hasNext()) + return true; + } + objectIt = null; + return false; + } + + @Override + public T next() { + if(!hasNext()) + throw new NoSuchElementException(); + return objectIt.next(); + } + + @Override + public void remove() { + throw new RuntimeException("Iterator is ReadOnly"); + } + } +} \ No newline at end of file diff --git a/src/zutil/plugin/plugin.json.example b/src/zutil/plugin/plugin.json.example new file mode 100644 index 00000000..5af4f95e --- /dev/null +++ b/src/zutil/plugin/plugin.json.example @@ -0,0 +1,8 @@ +{ + "version": 1.0, + "name": "Nice name of Plugin", + "interfaces": [ + {"plugin.interface.class": "plugin.implementation.class"}, + {"wa.server.plugin.WAFrontend": "wa.server.plugin.apache.ApacheFrontend"} + ] +} \ No newline at end of file diff --git a/src/zutil/struct/BloomFilter.java b/src/zutil/struct/BloomFilter.java new file mode 100644 index 00000000..9c21b7c4 --- /dev/null +++ b/src/zutil/struct/BloomFilter.java @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.struct; + +import zutil.Hasher; + +import java.io.Serializable; +import java.util.BitSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +/** + * A implementation of a bloom filter + * @author Ziver + * + */ +public class BloomFilter implements Set, Serializable{ + private static final long serialVersionUID = 1L; + + private BitSet bits; + private int content_size; + private int optimal_size; + private int k; + + + /** + * Creates a bloom filter + * + * @param size The amount of bits in the filter + * @param expected_data_count The estimated amount of data to + * be inserted(a bigger number is better than a smaller) + */ + public BloomFilter(int size, int expected_data_count){ + bits = new BitSet(size); + k = (int)((size/expected_data_count) * Math.log(2)); + content_size = 0; + optimal_size = expected_data_count; + } + + /** + * @param e A Serializable object + * @return If the optimal size has been reached + */ + public boolean add(T e) { + try { + content_size++; + int hash = 0; + for(int i=0; i c) { + for(T t : c){ + add(t); + } + return isFull(); + } + + /** + * @return clears the filter + */ + public void clear() { + content_size = 0; + bits.clear(); + } + + /** + * @param o is the Serializable object to search for + * @return If the object contains in the filter or + * false if the Object is not Serializable + */ + public boolean contains(Object o) { + try { + if(!(o instanceof Serializable))return false; + int hash = 0; + for(int i=0; i c) { + for(Object o : c){ + if(!contains(o)) return false; + } + return true; + } + + /** + * @return If the bloom filter is empty + */ + public boolean isEmpty() { + return content_size == 0; + } + + /** + * @return If the optimal size has been reached + */ + public boolean isFull() { + return content_size > optimal_size; + } + + /** + * @return The number of data added + */ + public int size() { + return content_size; + } + + /** + * @return The false positive probability of the current state of the filter + */ + public double falsePosetiveProbability(){ + return Math.pow(0.6185, bits.size()/content_size); + } + + /** + * Set the hash count. Should be set before adding elements + * or the already added elements will be lost + * + * @param k The hash count + */ + public void setHashCount(int k){ + this.k = k; + } + + //********************************************************************* + //********************************************************************* + public Object[] toArray() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("hiding") + public T[] toArray(T[] a) { + throw new UnsupportedOperationException(); + } + + public Iterator iterator() { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/zutil/struct/CircularBuffer.java b/src/zutil/struct/CircularBuffer.java new file mode 100755 index 00000000..c155bc21 --- /dev/null +++ b/src/zutil/struct/CircularBuffer.java @@ -0,0 +1,109 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.struct; + + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * This class is a first in first out circular buffer with a fixed size. + * If the size is exceed then the oldest item will be removed. + * Created by Ziver on 2015-09-22. + */ +public class CircularBuffer implements Iterable{ + + private Object[] buffer; + private int buffSize; + private int buffPos; + private long addCount; + + /** + * Initiates the buffer with a maximum size of maxSize. + */ + public CircularBuffer(int maxSize){ + buffer = new Object[maxSize]; + buffSize = 0; + buffPos = 0; + } + + public void add(T obj){ + if(buffPos+1 >= buffer.length) + buffPos = 0; + else + ++buffPos; + if(buffSize < buffer.length) + ++buffSize; + buffer[buffPos] = obj; + ++addCount; + } + + public T get(int index) { + if(index >= buffSize) + throw new IndexOutOfBoundsException("Index "+ index +" is larger than actual buffer size "+ buffSize); + int buffIndex = buffPos - index; + if(buffIndex < 0) + buffIndex = buffer.length - Math.abs(buffIndex); + return (T)buffer[buffIndex]; + } + + public int size() { + return buffSize; + } + + /** + * @return the total amount of insertions into the buffer, this value only increments and will never decrease. + */ + public long getInsertionCount() { + return addCount; + } + + @Override + public Iterator iterator() { + return new CircularBufferIterator(); + } + + + protected class CircularBufferIterator implements Iterator { + private int iteratorPos = 0; + + @Override + public boolean hasNext() { + return iteratorPos < buffSize; + } + + @Override + public T next() { + if(iteratorPos >= buffSize) + throw new NoSuchElementException(); + return get(iteratorPos++); + } + + @Override + public void remove() { + throw new UnsupportedOperationException (); + } + } +} diff --git a/src/zutil/struct/HistoryList.java b/src/zutil/struct/HistoryList.java new file mode 100644 index 00000000..8a25e429 --- /dev/null +++ b/src/zutil/struct/HistoryList.java @@ -0,0 +1,129 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.struct; + +import java.util.Iterator; +import java.util.LinkedList; + + +public class HistoryList implements Iterable{ + public int history_length; + private LinkedList history; + private int historyIndex = 0; + + /** + * Creates an HistoryList object + */ + public HistoryList(){ + this( Integer.MAX_VALUE ); + } + + /** + * Creates an HistoryList object with an max size + * + * @param histlength the maximum size of the list + */ + public HistoryList(int histlength){ + history_length = histlength; + history = new LinkedList(); + } + + /** + * Returns the item in the given index + * + * @param i is the index + * @return item in that index + */ + public T get(int i){ + return history.get( i ); + } + + /** + * Adds an item to the list and removes the last if + * the list is bigger than the max length. + * + * @param item is the item to add + */ + public void add(T item){ + while(historyIndex < history.size()-1){ + history.removeLast(); + } + history.addLast(item); + if(history_length < history.size()){ + history.removeFirst(); + } + + historyIndex = history.size()-1; + } + + /** + * @return the previous item in the list + */ + public T getPrevious(){ + if(historyIndex > 0){ + historyIndex -= 1; + } + else{ + historyIndex = 0; + } + return history.get(historyIndex); + } + + /** + * @return the next item in the list + */ + public T getNext(){ + if(next()){ + historyIndex += 1; + } + else{ + historyIndex = history.size()-1; + } + return history.get(historyIndex); + } + + public T getCurrent(){ + return history.get(historyIndex); + } + + /** + * @return if there are items newer than the current + */ + public boolean next(){ + if(historyIndex < history.size()-1){ + return true; + } + else{ + return false; + } + } + + /** + * @return an iterator of the list + */ + public Iterator iterator(){ + return history.iterator(); + } +} diff --git a/src/zutil/struct/MutableInt.java b/src/zutil/struct/MutableInt.java new file mode 100644 index 00000000..d293b1da --- /dev/null +++ b/src/zutil/struct/MutableInt.java @@ -0,0 +1,41 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.struct; + +/** + * A simple class that only contains a public int. Can be used in + * recursive functions as a persistent integer. + * + * @author Ziver + */ +public class MutableInt { + public int i = 0; + + public MutableInt(){} + + public MutableInt(int i){ + this.i = i; + } +} diff --git a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/OpenCloseTrait.java b/src/zutil/struct/TimedHashSet.java old mode 100644 new mode 100755 similarity index 51% rename from plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/OpenCloseTrait.java rename to src/zutil/struct/TimedHashSet.java index 7d85277a..bb249c1e --- a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/OpenCloseTrait.java +++ b/src/zutil/struct/TimedHashSet.java @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Ziver Koc + * Copyright (c) 2015 Ziver Koc * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,42 +22,52 @@ * THE SOFTWARE. */ -package se.hal.plugin.assistant.google.trait; - - -import se.hal.intf.HalDeviceConfig; -import se.hal.intf.HalDeviceData; -import se.hal.struct.devicedata.OnOffEventData; -import se.hal.struct.devicedata.OpenClosedEventData; +package zutil.struct; import java.util.HashMap; - /** - * https://developers.google.com/assistant/smarthome/traits/openclose + * This is a timed HashSet. Each entry has a limited time to live. */ -public class OpenCloseTrait extends DeviceTrait { +public class TimedHashSet { - @Override - String getId() { - return "action.devices.traits.OpenClose"; + private HashMap map; + private long ttl; + + /** + * @param ttl milliseconds the entries will live + */ + public TimedHashSet(long ttl){ + this.ttl = ttl; + this.map = new HashMap<>(); } - @Override - public HashMap generateSyncResponse(HalDeviceConfig config) { - HashMap response = new HashMap<>(); - response.put("queryOnlyOnOff", true); - return response; + + /** + * @return true if the object already existed in the set which will reset the TTL. + */ + public boolean add(T o){ + return map.put(o, System.currentTimeMillis()) != null; } - @Override - public HashMap generateQueryResponse(HalDeviceData data) { - HashMap response = new HashMap<>(); - - if (data instanceof OpenClosedEventData) { - response.put("openPercent", ((OpenClosedEventData) data).isOpen() ? 100 : 0); + public boolean contains(Object o){ + if(map.containsKey(o)){ + if(map.get(o) + ttl < System.currentTimeMillis()) // entry to old + map.remove(o); + else + return true; } + return false; + } - return response; + + /** + * Iterates through the Set and removes all entries that has passed the TTL + */ + public void garbageCollect(){ + for(T o : map.keySet()){ + if(map.get(o) + ttl < System.currentTimeMillis()) // entry to old + map.remove(o); + } } } diff --git a/src/zutil/ui/Configurator.java b/src/zutil/ui/Configurator.java new file mode 100755 index 00000000..a9befe8b --- /dev/null +++ b/src/zutil/ui/Configurator.java @@ -0,0 +1,284 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui; + +import zutil.log.LogUtil; +import zutil.parser.DataNode; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Created by Ziver + */ +public class Configurator { + private static final Logger logger = LogUtil.getLogger(); + + /** + * Sets a field in a class as externally configurable. + */ + @Retention(RetentionPolicy.RUNTIME) // Make this annotation accessible at runtime via reflection. + @Target({ElementType.FIELD}) // This annotation can only be applied to class fields. + public static @interface Configurable{ + /** Nice name of this parameter **/ + String value(); + /** Defines the order the parameters, in ascending order **/ + int order() default Integer.MAX_VALUE; + } + + + public static enum ConfigType{ + STRING, INT, BOOLEAN + } + + + private static HashMap classConf = new HashMap<>(); + + private T obj; + private ConfigurationParam[] params; + private PreConfigurationActionListener preListener; + private PostConfigurationActionListener postListener; + + public Configurator(T obj){ + this.obj = obj; + this.params = getConfiguration(obj.getClass(), obj); + } + + public T getObject(){ + return obj; + } + + public ConfigurationParam[] getConfiguration(){ + return params; + } + + public static ConfigurationParam[] getConfiguration(Class c){ + if(!classConf.containsKey(c)) + classConf.put(c, getConfiguration(c, null)); + return classConf.get(c); + } + protected static ConfigurationParam[] getConfiguration(Class c, Object obj){ + ArrayList conf = new ArrayList(); + + Field[] all = c.getDeclaredFields(); + for(Field f : all){ + if(f.isAnnotationPresent(Configurable.class) && + !Modifier.isStatic(f.getModifiers()) && !Modifier.isTransient(f.getModifiers())) { + try { + conf.add(new ConfigurationParam(f, obj)); + } catch (IllegalAccessException e) { + logger.log(Level.SEVERE, null, e); + } + } + } + + ConfigurationParam[] list = conf.toArray(new ConfigurationParam[conf.size()]); + Arrays.sort(list); + return list; + } + + /** + * Uses a Map to assign all parameters of the Object + */ + public Configurator setValues(Map parameters){ + for(ConfigurationParam param : this.params){ + if(parameters.containsKey(param.getName())) + param.setValue(parameters.get(param.getName())); + } + return this; + } + + /** + * Uses a Map to assign all parameters of the Object. + * NOTE: the DataNode must be of type Map + */ + public Configurator setValues(DataNode node){ + if(!node.isMap()) + return this; + for(ConfigurationParam param : this.params){ + if(node.get(param.getName()) != null) + param.setValue(node.getString(param.getName())); + } + return this; + } + + public DataNode getValuesAsNode(){ + DataNode node = new DataNode(DataNode.DataType.Map); + for(ConfigurationParam param : this.params){ + node.set(param.getName(), param.getString()); + } + return node; + } + + + /** + * Set a listener that will be called just before the configuration has been applied + */ + public void setPreConfigurationListener(PreConfigurationActionListener listener){ + preListener = listener; + } + + /** + * Set a listener that will be called after the configuration has been applied + */ + public void setPostConfigurationListener(PostConfigurationActionListener listener){ + postListener = listener; + } + + /** + * All configuration parameters that was set + * for each parameter will be applied to the object. + * + * The preConfigurationAction() method will be called before the target object has + * been configured if it implements the PreConfigurationActionListener interface. + * The postConfigurationAction() method will be called after the target object is + * configured if it implements the PostConfigurationActionListener interface. + */ + public void applyConfiguration(){ + if(preListener != null) + preListener.preConfigurationAction(this, obj); + if(obj instanceof PreConfigurationActionListener) + ((PreConfigurationActionListener) obj).preConfigurationAction(this, obj); + + StringBuilder strParams = new StringBuilder(); + for(ConfigurationParam param : params){ + try { + param.apply(obj); + // Logging + if(logger.isLoggable(Level.FINE)) { + strParams.append(param.getName()); + if(param.isTypeString()) + strParams.append(": '").append(param.getString()).append("', "); + else + strParams.append(": ").append(param.getString()).append(", "); + } + } catch (IllegalAccessException e) { + logger.log(Level.WARNING, null, e); + } + } + if(logger.isLoggable(Level.FINE)) + logger.fine("Configured object: " + obj.getClass().getName() + " ("+ strParams +")"); + + if(obj instanceof PostConfigurationActionListener) + ((PostConfigurationActionListener) obj).postConfigurationAction(this, obj); + if(postListener != null) + postListener.postConfigurationAction(this, obj); + } + + + public interface PreConfigurationActionListener { + void preConfigurationAction(Configurator configurator, T obj); + } + public interface PostConfigurationActionListener { + void postConfigurationAction(Configurator configurator, T obj); + } + + + public static class ConfigurationParam implements Comparable{ + protected Field field; + protected String name; + protected String niceName; + protected ConfigType type; + protected Object value; + protected int order; + + + protected ConfigurationParam(Field f, Object obj) throws IllegalAccessException { + field = f; + field.setAccessible(true); + name = field.getName(); + if(obj != null) + value = field.get(obj); + if(field.isAnnotationPresent(Configurable.class)) { + niceName = field.getAnnotation(Configurable.class).value(); + order = field.getAnnotation(Configurable.class).order(); + } + else{ + niceName = name; + order = Integer.MAX_VALUE; + } + + if (f.getType() == String.class) type = ConfigType.STRING; + else if(f.getType() == int.class) type = ConfigType.INT; + else if(f.getType() == boolean.class)type = ConfigType.BOOLEAN; + + } + + public String getName(){ return name;} + public String getNiceName(){ return niceName;} + public ConfigType getType(){ return type;} + public boolean isTypeString(){ return type == ConfigType.STRING;} + public boolean isTypeInt(){ return type == ConfigType.INT;} + public boolean isTypeBoolean(){return type == ConfigType.BOOLEAN;} + + public String getString(){ + if(value == null) + return null; + return value.toString(); + } + public boolean getBoolean(){ + if(value == null || type != ConfigType.BOOLEAN) + return false; + return (boolean)value; + } + + /** + * This method will set a value for the represented field, + * to apply the change to the source object the method + * {@link #applyConfiguration()} needs to be called + */ + public void setValue(String v){ + switch(type){ + case STRING: + value = v; break; + case INT: + value = Integer.parseInt(v); break; + case BOOLEAN: + value = Boolean.parseBoolean(v); break; + } + } + + protected void apply(Object obj) throws IllegalAccessException { + if(obj != null) + field.set(obj, value); + } + + + @Override + public int compareTo(ConfigurationParam configurationParam) { + return this.order - configurationParam.order; + } + } +} diff --git a/src/zutil/ui/Console.java b/src/zutil/ui/Console.java new file mode 100644 index 00000000..e41f54b9 --- /dev/null +++ b/src/zutil/ui/Console.java @@ -0,0 +1,315 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui; + +import zutil.io.file.FileUtil; + +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; +import java.awt.TrayIcon.MessageType; +import java.awt.event.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; + +/** + * Creates a Swing console window That takes System.in and + * System.out as Streams and has the ability to stay in the tray + * when closed + * + * @author Ziver + * + */ +public class Console{ + public static String DEFAULT_ICON = "zutil/data/JavaConsole.png"; + // UI things + private JFrame frame; + private JTextPane console; + private Document doc; + private TrayIcon trayIcon; + private int bufferSize; + + public Console(String title){ + this(title, 680, 340, 50000, false); + } + + public Console(String title, boolean tray){ + this(title, 680, 340, 50000, tray); + } + + public Console(String title, int width, int height, int buffer, boolean tray){ + ConsoleInputStream in = new ConsoleInputStream(); + DEFAULT_ICON = FileUtil.find(DEFAULT_ICON).getAbsolutePath(); + initUI(title, in); + + bufferSize = buffer; + System.setOut(new ConsolePrintStream(System.out, Color.white)); + System.setErr(new ConsolePrintStream(System.out, Color.red, TrayIcon.MessageType.ERROR)); + System.setIn(in); + + enableTray(tray); + setFrameIcon(Toolkit.getDefaultToolkit().getImage(DEFAULT_ICON)); + frame.setSize(width, height); + frame.setVisible(true); + } + + /** + * initiates the ui + */ + private void initUI(String title, KeyListener listener){ + frame = new JFrame(title); + + console = new JTextPane(); + console.setBackground(Color.black); + console.setForeground(Color.white); + console.setFont(new Font("Lucida Console", Font.BOLD, 11)); + console.setEditable(false); + console.addKeyListener(listener); + doc = new DefaultStyledDocument(); + console.setDocument(doc); + + JScrollPane scroll = new JScrollPane(console, + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + + frame.add(scroll, BorderLayout.CENTER); + } + + public void setIcon(){ + + } + + public void appendConsole(String s, Style style){ + try { + doc.insertString(doc.getLength(), s, style); + if(doc.getLength() > bufferSize){ + doc.remove(0, doc.getLength() - bufferSize); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * Enables the tray icon and sets the icon + * @param img The image to use as the icon + */ + public void setTrayIcon(Image img){ + enableTray(true); + trayIcon.setImage(img); + } + + /** + * Sets the icon for the Frame + * + * @param img The image to use as a icon + */ + public void setFrameIcon(Image img){ + frame.setIconImage(img); + } + + /** + * Enables the go down to tray functionality + * + * @param enable if tray icon is enabled + */ + public void enableTray(boolean enable){ + if(enable && SystemTray.isSupported()){ + frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + SystemTray tray = SystemTray.getSystemTray(); + + if(trayIcon == null){ + // Menu + PopupMenu menu = new PopupMenu(); + MenuItem item = new MenuItem("Open"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frame.setVisible(true); + } + }); + menu.add(item); + menu.addSeparator(); + item = new MenuItem("Exit"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + menu.add(item); + + // Icon + trayIcon = new TrayIcon( + Toolkit.getDefaultToolkit().getImage(DEFAULT_ICON), + "Console", menu); + trayIcon.setImageAutoSize(true); + trayIcon.addMouseListener(new MouseListener(){ + public void mouseClicked(MouseEvent e) { + if(e.getClickCount() == 2) + frame.setVisible(true); + } + public void mouseEntered(MouseEvent e) {} + public void mouseExited(MouseEvent e) {} + public void mousePressed(MouseEvent e) {} + public void mouseReleased(MouseEvent e) {} + }); + } + + try { + tray.add(trayIcon); + } catch (AWTException e) { + System.err.println("TrayIcon could not be added."); + } + } + else{ + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + SystemTray.getSystemTray().remove(trayIcon); + } + } + + + /** + * The Stream to replace System.out + * + * @author Ziver + * + * TrayIcon.MessageType.ERROR An error message + * TrayIcon.MessageType.INFO An information message + * TrayIcon.MessageType.NONE A simple message + * TrayIcon.MessageType.WARNING A warning message + */ + private class ConsolePrintStream extends PrintStream{ + private Style style; + private MessageType trayMessageType; + + public ConsolePrintStream(OutputStream out, Color c) { + this(out, c, null); + } + + public ConsolePrintStream(OutputStream out, Color c, MessageType type) { + super(out); + style = console.addStyle("PrintStream", null); + StyleConstants.setForeground(style, c); + trayMessageType = type; + } + + public void print(String s){ + appendConsole(s, style); + console.setCaretPosition(console.getDocument().getLength()); + if(trayMessageType != null && trayIcon != null){ + trayIcon.displayMessage( + s.substring(0, (s.length() > 25 ? 25 : s.length()))+"...", + s, trayMessageType); + + } + } + + public void println(String s){ + print(s+"\n"); + } + + public void println(){ println("");} + public void println(boolean x){ println(""+x);} + public void println(char x){ println(""+x);} + public void println(char[] x){ println(new String(x));} + public void println(double x){ println(""+x);} + public void println(float x){ println(""+x);} + public void println(int x){ println(""+x);} + public void println(long x){ println(""+x);} + public void println(Object x){ println(""+x);} + + public void print(boolean x){ print(""+x);} + public void print(char x){ print(""+x);} + public void print(char[] x){ print(new String(x));} + public void print(double x){ print(""+x);} + public void print(float x){ print(""+x);} + public void print(int x){ print(""+x);} + public void print(long x){ print(""+x);} + public void print(Object x){ print(""+x);} + } + + private class ConsoleInputStream extends InputStream implements KeyListener{ + private boolean read = false; + private int input; + + @Override + public int read() throws IOException { + if(input < 0) { + input = 0; + return -1; + } + + read = true; + input = 0; + while(input == 0){ + try {Thread.sleep(10);} catch (InterruptedException e) {} + } + read = false; + + System.out.print((char)input); + if(input == KeyEvent.VK_ENTER){ + input = -1; + return '\n'; + } + return input; + } + /* + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + System.out.println(off+"-"+len); + int i; + for(i=-1; i +WizardManager.back.text=< Back +WizardManager.pageTitle.text= diff --git a/src/zutil/ui/wizard/Wizard.java b/src/zutil/ui/wizard/Wizard.java new file mode 100644 index 00000000..85de8d37 --- /dev/null +++ b/src/zutil/ui/wizard/Wizard.java @@ -0,0 +1,358 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui.wizard; + +import zutil.io.MultiPrintStream; +import zutil.io.file.FileUtil; +import zutil.struct.HistoryList; +import zutil.ui.JImagePanel; +import zutil.ui.wizard.listener.BlockingWizardListener; + +import javax.imageio.ImageIO; +import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import javax.swing.LayoutStyle.ComponentPlacement; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.ResourceBundle; + +/** + * This class manages the whole wizard + * + * @author Ziver + */ +public class Wizard implements ActionListener{ + public static final boolean DEBUG = false; + + /** Some defoult backgrounds for the sidebar */ + public static final String BACKGROUND_1 = "zutil/data/wizard1.jpg"; + public static final String BACKGROUND_2 = "zutil/data/wizard2.jpg"; + public static final String BACKGROUND_3 = "zutil/data/wizard3.png"; + + /** An list with all the previous pages and the current at the beginning */ + private HistoryList pages; + /** HashMap containing all the selected values */ + private HashMap values; + /** The general component listener */ + private WizardActionHandler handler; + /** This is the user listener that handles all the values after the wizard */ + private WizardListener listener; + + /** This is the old validation fail, this is needed for reseting purposes */ + private ValidationFail oldFail; + + + private Wizard(WizardListener listener){ + this(listener, null); + } + + /** + * Creates a new Wizard + */ + public Wizard(WizardListener listener, WizardPage start){ + this(listener, start, BACKGROUND_1); + } + + /** + * Creates a new Wizard + * + * @param start is the first page in the wizard + * @param bg is the background image to use + */ + public Wizard(WizardListener listener, final WizardPage start, final String bg){ + try { + this.listener = listener; + pages = new HistoryList(); + values = new HashMap(); + handler = new WizardActionHandler( values ); + + // GUI + frame = new JFrame(); + initComponents(); + sidebar.scale( false ); + + // add action listener to the buttons + back.addActionListener( this ); + next.addActionListener( this ); + cancel.addActionListener( this ); + finish.addActionListener( this ); + + // Set the image in the sidebar + sidebar.setImage(ImageIO.read( FileUtil.getInputStream( bg ) )); + + // add the first page + pages.add( start ); + displayWizardPage( start ); + + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + } + + /** + * Sets the title of the Wizard + */ + public void setTitle(String s){ + frame.setTitle(s); + } + + /** + * Sets the size of the Wizard frame + * + * @param w is the width + * @param h is the height + */ + public void setSize(int w, int h){ + frame.setSize(w, h); + } + + /** + * Displays the wizard + */ + public void start(){ + frame.setVisible(true); + } + + /** + * @return the JFrame used for the wizard + */ + public JFrame getFrame(){ + return frame; + } + + /** + * Set the current WizardPage + * + * @param page is the page to be displayed + */ + protected void displayWizardPage(WizardPage page){ + pageContainer.getViewport().setView(page); + pageTitle.setText( page.getPageDescription() ); + } + + public void actionPerformed(ActionEvent e) { + // Back Button + if(e.getSource() == back){ + WizardPage page = pages.getPrevious(); + displayWizardPage( page ); + if(pages.get(0) == page){ + back.setEnabled( false ); + } + } + // Next Button and Finish Button + else if(e.getSource() == next || e.getSource() == finish){ + WizardPage page = pages.getCurrent(); + page.registerValues( handler ); + if(DEBUG) MultiPrintStream.out.println(values); + + ValidationFail fail = page.validate( values ); + if(fail != null){ + // reset old fail + if(oldFail != null) oldFail.getSource().setBorder( BorderFactory.createEmptyBorder() ); + if(fail.getSource() != null) + fail.getSource().setBorder( BorderFactory.createLineBorder(Color.RED) ); + //pageStatus.setText( fail.getMessage() ); + } + else if(e.getSource() == finish){ + frame.dispose(); + listener.onFinished( values ); + } + else if(e.getSource() == next){ + WizardPage nextPage = page.getNextPage( values ); + if(nextPage == null){ + frame.dispose(); + listener.onCancel(page, values ); + return; + } + pages.add( nextPage ); + displayWizardPage( nextPage ); + back.setEnabled( true ); + if( nextPage.isFinalPage() ){ + next.setEnabled( false ); + finish.setEnabled( true ); + } + } + } + // Cancel Button + else if(e.getSource() == cancel){ + frame.dispose(); + listener.onCancel(pages.getCurrent(), values ); + } + } + + + private void initComponents() { + cancel = new JButton(); + finish = new JButton(); + next = new JButton(); + back = new JButton(); + + JSeparator separator = new JSeparator(); // NOI18N + sidebar = new JImagePanel(); + JLabel steps = new JLabel(); + JSeparator separator2 = new JSeparator(); + pageTitle = new JLabel(); + JSeparator separator3 = new JSeparator(); + error = new JLabel(); + pageContainer = new JScrollPane(); + + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + ResourceBundle bundle = ResourceBundle.getBundle("zutil/ui/wizard/Bundle"); + cancel.setText(bundle.getString("WizardManager.cancel.text")); // NOI18N + + finish.setText(bundle.getString("WizardManager.finish.text")); // NOI18N + finish.setEnabled(false); + + next.setText(bundle.getString("WizardManager.next.text")); // NOI18N + + back.setText(bundle.getString("WizardManager.back.text")); // NOI18N + back.setEnabled(false); + + sidebar.setBorder(BorderFactory.createEtchedBorder()); + + steps.setText(bundle.getString("WizardManager.steps.text")); // NOI18N + + GroupLayout sidebarLayout = new GroupLayout(sidebar); + sidebar.setLayout(sidebarLayout); + sidebarLayout.setHorizontalGroup( + sidebarLayout.createParallelGroup(Alignment.LEADING) + .addGroup(sidebarLayout.createSequentialGroup() + .addContainerGap() + .addGroup(sidebarLayout.createParallelGroup(Alignment.LEADING) + .addComponent(separator2, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE) + .addComponent(steps, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE)) + .addContainerGap()) + ); + sidebarLayout.setVerticalGroup( + sidebarLayout.createParallelGroup(Alignment.LEADING) + .addGroup(sidebarLayout.createSequentialGroup() + .addGap(23, 23, 23) + .addComponent(steps) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(separator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) + .addContainerGap(347, Short.MAX_VALUE)) + ); + + pageTitle.setFont(new Font("Tahoma", 1, 18)); + pageTitle.setText(bundle.getString("WizardManager.pageTitle.text")); // NOI18N + + error.setFont(new Font("Times New Roman", 1, 12)); + error.setForeground(new Color(255, 0, 0)); + error.setText(bundle.getString("WizardManager.error.text")); // NOI18N + + pageContainer.setBorder(null); + + GroupLayout layout = new GroupLayout(frame.getContentPane()); + frame.getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(error, GroupLayout.DEFAULT_SIZE, 371, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(back) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(next) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(finish) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(cancel) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addComponent(sidebar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addGroup(layout.createParallelGroup(Alignment.TRAILING) + .addComponent(separator, GroupLayout.DEFAULT_SIZE, 492, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(pageTitle, GroupLayout.DEFAULT_SIZE, 492, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.RELATED))) + .addGap(2, 2, 2)) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(separator3, GroupLayout.DEFAULT_SIZE, 494, Short.MAX_VALUE) + .addComponent(pageContainer, GroupLayout.DEFAULT_SIZE, 494, Short.MAX_VALUE))))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(Alignment.TRAILING) + .addComponent(sidebar, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(Alignment.LEADING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(pageTitle, GroupLayout.PREFERRED_SIZE, 30, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(separator3, GroupLayout.PREFERRED_SIZE, 2, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(pageContainer, GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(separator, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(cancel) + .addComponent(finish) + .addComponent(next) + .addComponent(back) + .addComponent(error)) + .addContainerGap()) + ); + + frame.pack(); + } + + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + final BlockingWizardListener listener = new BlockingWizardListener(); + EventQueue.invokeLater(new Runnable() { + public void run() { + Wizard wizard = new Wizard(listener); + wizard.start(); + } + }); + MultiPrintStream.out.dump( listener.getValues() ); + + } + + // Variables declaration - do not modify + private JLabel error; + private JButton back; + private JButton cancel; + private JButton finish; + private JButton next; + private JScrollPane pageContainer; + private JLabel pageTitle; + private JImagePanel sidebar; + private JFrame frame; + // End of variables declaration + +} diff --git a/src/zutil/ui/wizard/WizardActionHandler.java b/src/zutil/ui/wizard/WizardActionHandler.java new file mode 100644 index 00000000..3cbbe1ea --- /dev/null +++ b/src/zutil/ui/wizard/WizardActionHandler.java @@ -0,0 +1,122 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui.wizard; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.util.HashMap; + +public class WizardActionHandler implements ActionListener, FocusListener, ListSelectionListener{ + private HashMap values; + + public WizardActionHandler(HashMap values){ + this.values = values; + } + + public void actionPerformed(ActionEvent e) { + event(e); + } + public void focusGained(FocusEvent e) { + event(e); + } + public void focusLost(FocusEvent e) { + event(e); + } + public void event(AWTEvent e){ + if(e.getSource() instanceof Component) + registerValue( (Component)e.getSource() ); + } + public void valueChanged(ListSelectionEvent e) { + if(e.getSource() instanceof Component) + registerValue( (Component)e.getSource() ); + } + + public void registerListener(Component c){ + /** + * JToggleButton + * JCheckBox + * JRadioButton + */ + if(c instanceof JToggleButton){ + JToggleButton o = (JToggleButton) c; + o.addActionListener( this ); + } + /** + * JEditorPane + * JTextArea + * JTextField + */ + else if(c instanceof JTextComponent){ + JTextComponent o = (JTextComponent) c; + o.addFocusListener( this ); + } + /** + * JList + */ + else if(c instanceof JList){ + JList o = (JList) c; + o.addListSelectionListener( this ); + } + } + + /** + * Registers the state of the event source + * @param e is the event + */ + public void registerValue(Component c) { + /** + * JToggleButton + * JCheckBox + * JRadioButton + */ + if(c instanceof JToggleButton){ + JToggleButton o = (JToggleButton) c; + values.put( o.getName() , o.isSelected() ); + } + /** + * JEditorPane + * JTextArea + * JTextField + */ + else if(c instanceof JTextComponent){ + JTextComponent o = (JTextComponent) c; + values.put( o.getName() , o.getText() ); + } + /** + * JList + */ + else if(c instanceof JList){ + JList o = (JList) c; + values.put( o.getName() , o.getSelectedValue() ); + } + } +} diff --git a/src/zutil/ui/wizard/WizardListener.java b/src/zutil/ui/wizard/WizardListener.java new file mode 100644 index 00000000..4111e624 --- /dev/null +++ b/src/zutil/ui/wizard/WizardListener.java @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui.wizard; + +import java.util.HashMap; + +public interface WizardListener { + + /** + * Will be called when the cancel button is pressed + * + * @param page is the WizardPage where the cancel button was pressed + * @param values is the values until now + */ + public void onCancel(WizardPage page, HashMap values); + + /** + * Will be called when the wizard is finished + * + * @param values is the values until now + */ + public void onFinished(HashMap values); +} diff --git a/src/zutil/ui/wizard/WizardPage.java b/src/zutil/ui/wizard/WizardPage.java new file mode 100644 index 00000000..7b63b78b --- /dev/null +++ b/src/zutil/ui/wizard/WizardPage.java @@ -0,0 +1,151 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui.wizard; + +import javax.swing.*; +import java.awt.*; +import java.util.HashMap; +import java.util.LinkedList; + +/** + * This abstract class is one step in the wizard + * + * @author Ziver + */ +public abstract class WizardPage extends JPanel{ + private static final long serialVersionUID = 1L; + + /** contains the components whom values will be saved */ + private LinkedList components; + /** if this is the last page in the wizard */ + private boolean lastPage = false; + + public WizardPage(){ + components = new LinkedList(); + } + + /** + * Register a component whom the value will be saved with + * the key that is what getName returns from the component + * and passed on to the other pages. + * + * @param c is the component + */ + public void registerComponent(Component c){ + components.add( c ); + } + + /** + * Sets if this is the last page in the wizard, + * Should be called as early as possible. + */ + public void setFinalPage(boolean b){ + lastPage = b; + } + + /** + * @return is this is the last page in the wizard + */ + public boolean isFinalPage(){ + return lastPage; + } + + /** + * @return the next page in the wizard, + * is called when the next button is pressed, + * return null to end the wizard + */ + public abstract WizardPage getNextPage(HashMap values); + + /** + * @return a very short description of this page + */ + public abstract String getPageDescription(); + + + /** + * This method is called when the next button is pressed + * and the input values are going to be validated. + * + * @param values is the values until now + * @return a ValidateFail object or null if the validation passed + */ + public ValidationFail validate(HashMap values){ + return null; + } + + /** + * Will be called after the validation passes and will + * save all the states of the registered components + * + * @param listener is the object that handles the save process + */ + public void registerValues(WizardActionHandler listener){ + for(Component c : components){ + listener.registerValue( c ); + } + } +} + +/** + * This class is for failed validations + * + * @author Ziver + */ +class ValidationFail{ + /** The component that failed the validation */ + private JComponent source; + /** An message to the user about the fault */ + private String msg; + + /** + * Creates an ValidationFail object + * + * @param c is the component that failed the validation + * @param msg is a message to the user about the fault + */ + public ValidationFail(String msg){ + this(null, msg); + } + + /** + * Creates an ValidationFail object + * + * @param c is the component that failed the validation + * @param msg is a message to the user about the fault + */ + public ValidationFail(JComponent c, String msg){ + this.source = c; + this.msg = msg; + } + + public JComponent getSource(){ + return source; + } + + public String getMessage(){ + return msg; + } +} diff --git a/src/zutil/ui/wizard/listener/BlockingWizardListener.java b/src/zutil/ui/wizard/listener/BlockingWizardListener.java new file mode 100644 index 00000000..30b0e9ba --- /dev/null +++ b/src/zutil/ui/wizard/listener/BlockingWizardListener.java @@ -0,0 +1,69 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui.wizard.listener; + +import zutil.ui.wizard.WizardListener; +import zutil.ui.wizard.WizardPage; + +import java.util.HashMap; + +/** + * This listener class will block until the wizard is finished + * and than return the values of the wizard + * + * @author Ziver + */ +public class BlockingWizardListener implements WizardListener{ + private HashMap values; + + /** + * Will block until the wizard is finished + * + * @return the values with a extra parameter "canceled" set + * as a boolean if the wizard was canceled and "canceledPage" + * witch is the page where the cancel button was pressed + */ + public HashMap getValues(){ + while(values == null){ + try{ + Thread.sleep(100); + }catch(Exception e){} + } + return values; + } + + + public void onCancel(WizardPage page, HashMap values) { + values.put("canceled", Boolean.TRUE); + values.put("canceledPage", page); + this.values = values; + } + + public void onFinished(HashMap values) { + values.put("canceled", Boolean.FALSE); + this.values = values; + } + +} diff --git a/src/zutil/ui/wizard/page/SummaryPage.java b/src/zutil/ui/wizard/page/SummaryPage.java new file mode 100755 index 00000000..0a73eb83 --- /dev/null +++ b/src/zutil/ui/wizard/page/SummaryPage.java @@ -0,0 +1,70 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui.wizard.page; + +import zutil.ui.wizard.WizardPage; + +import javax.swing.*; +import java.util.HashMap; + +/** + * This class will show a summary of all the values + * in the wizard + * + * @author Ziver + * + */ +public class SummaryPage extends WizardPage{ + private static final long serialVersionUID = 1L; + + public SummaryPage(HashMap values){ + this.setFinalPage( true ); + + JTextArea summary = new JTextArea(); + summary.setEditable(false); + summary.setEnabled(false); + this.add( summary ); + + StringBuffer tmp = new StringBuffer(); + for(String key : values.keySet()){ + tmp.append(key); + tmp.append(": "); + tmp.append(values.get( key )); + tmp.append("\n"); + } + summary.setText( tmp.toString() ); + } + + @Override + public WizardPage getNextPage(HashMap values) { + return null; + } + + @Override + public String getPageDescription() { + return "Summary"; + } + +} diff --git a/src/zutil/wrapper/SerializableBufferedImage.java b/src/zutil/wrapper/SerializableBufferedImage.java new file mode 100644 index 00000000..9f2e96a3 --- /dev/null +++ b/src/zutil/wrapper/SerializableBufferedImage.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.wrapper; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +public class SerializableBufferedImage implements Serializable{ + private static final long serialVersionUID = 1L; + + private BufferedImage image; + + public SerializableBufferedImage(BufferedImage image){ + this.image = image; + } + + public BufferedImage getImage(){ + return image; + } + + public void setImage(BufferedImage image){ + this.image=image; + } + + private void writeObject(ObjectOutputStream out)throws IOException{ + ImageIO.write(image,"jpeg",ImageIO.createImageOutputStream(out)); + } + + private void readObject(ObjectInputStream in)throws IOException, ClassNotFoundException{ + image = ImageIO.read(ImageIO.createImageInputStream(in)); + } +} diff --git a/test/zutil/ByteUtilTest.java b/test/zutil/ByteUtilTest.java new file mode 100755 index 00000000..96a560b8 --- /dev/null +++ b/test/zutil/ByteUtilTest.java @@ -0,0 +1,48 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +/** + * Created by Ziver on 2016-01-31. + */ +public class ByteUtilTest { + + + @Test + public void getShiftedBits(){ + assertEquals(1, ByteUtil.getShiftedBits((byte)0b1000_0000, 7, 1)); + assertEquals(1, ByteUtil.getShiftedBits((byte)0b0001_0000, 4, 1)); + assertEquals(1, ByteUtil.getShiftedBits((byte)0b0000_0001, 0, 1)); + + assertEquals(3, ByteUtil.getShiftedBits((byte)0b0110_0000, 6, 2)); + + assertEquals((byte)0xFF, ByteUtil.getShiftedBits((byte)0b1111_1111, 7, 8)); + } +} diff --git a/test/zutil/EncrypterTest.java b/test/zutil/EncrypterTest.java new file mode 100755 index 00000000..40352e03 --- /dev/null +++ b/test/zutil/EncrypterTest.java @@ -0,0 +1,73 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil; + +import org.junit.Test; +import zutil.Encrypter.Algorithm; + +import static org.junit.Assert.assertEquals; + + +public class EncrypterTest { + public static final String data = "Hello there, wats yor name, my is a secret, 123456789"; + public static final String key = "abcdefghijklmnopqrstuvwxyz"; + + + @Test + public void encryptDES() throws Exception { + Encrypter.randomizeSalt(); + Encrypter encrypter = new Encrypter(key, Algorithm.DES); + Encrypter decrypter = new Encrypter(key, Algorithm.DES); + + assertEquals(data, encryptDecrypt(encrypter, decrypter, data)); + } + + @Test + public void encryptBLOWFISH() throws Exception { + Encrypter.randomizeSalt(); + Encrypter encrypter = new Encrypter(Algorithm.Blowfish); + Encrypter.randomizeSalt(); + Encrypter decrypter = new Encrypter(encrypter.getKey()); + + assertEquals(data, encryptDecrypt(encrypter, decrypter, data)); + } + + @Test + public void encryptAES() throws Exception { + Encrypter.randomizeSalt(); + Encrypter encrypter = new Encrypter(key, Algorithm.AES); + Encrypter decrypter = new Encrypter(key, Algorithm.AES); + + assertEquals(data, encryptDecrypt(encrypter, decrypter, data)); + } + + + + public static String encryptDecrypt(Encrypter encrypter, Encrypter decrypter, String data){ + byte[] encrypted = encrypter.encrypt(data.getBytes()); + byte[] decrypted = decrypter.decrypt(encrypted); + return new String(decrypted); + } +} diff --git a/test/zutil/HasherTest.java b/test/zutil/HasherTest.java new file mode 100755 index 00000000..03a54d44 --- /dev/null +++ b/test/zutil/HasherTest.java @@ -0,0 +1,51 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +public class HasherTest { + + @Test + public void MD5Test(){ + assertEquals(Hasher.MD5("AAAABBBB"), "9da4fc50e09e5eeb8ae8149ef4f23792"); + assertEquals(Hasher.MD5("qwerty12345"), "85064efb60a9601805dcea56ec5402f7"); + assertEquals(Hasher.MD5("123456789"), "25f9e794323b453885f5181f1b624d0b"); + //assertEquals(Hasher.MD5(".,<>|!#�%&/()=?"), "20d5cda029514fa49a8bbe854a539847"); + assertEquals(Hasher.MD5("Test45"), "fee43a4c9d88769e14ec6a1d8b80f2e7"); + } + + @Test + public void SHA1Test(){ + assertEquals(Hasher.SHA1("AAAABBBB"), "7cd188ef3a9ea7fa0ee9c62c168709695460f5c0"); + assertEquals(Hasher.SHA1("qwerty12345"), "4e17a448e043206801b95de317e07c839770c8b8"); + assertEquals(Hasher.SHA1("123456789"), "f7c3bc1d808e04732adf679965ccc34ca7ae3441"); + //assertEquals(Hasher.SHA1(".,<>|!#�%&/()=?"), "6b3de029cdb367bb365d5154a197294ee590a77a"); + assertEquals(Hasher.SHA1("Test45"), "9194c6e64a6801e24e63a924d5843a46428d2b3a"); + } +} diff --git a/test/zutil/StringUtilTest.java b/test/zutil/StringUtilTest.java new file mode 100755 index 00000000..3b6cfe21 --- /dev/null +++ b/test/zutil/StringUtilTest.java @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil; + +import org.junit.Test; +import zutil.StringUtil; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + + +public class StringUtilTest { + + @Test + public void formatByteSizeToStringTest() { + assertEquals( "100.0 B", StringUtil.formatByteSizeToString(100) ); + assertEquals( "9.7 kB", StringUtil.formatByteSizeToString(10000) ); + } + + @Test + public void formatTimeToStringTest() { + assertEquals( "1 sec ", StringUtil.formatTimeToString( 1000 ) ); + assertEquals( "1 month 1 day 1 hour 1 min 1 sec 1 milisec ", + StringUtil.formatTimeToString( 2629743830l+86400000+3600000+60000+1000+1 ) ); + assertEquals( "2 months 2 days 2 hours 2 min 2 sec 2 milisec ", + StringUtil.formatTimeToString( (2629743830l+86400000+3600000+60000+1000+1)*2 ) ); + } + + @Test + public void trimTest() { + assertEquals( "", StringUtil.trim("", ' ') ); + assertEquals( "aa", StringUtil.trim(" aa ", ' ') ); + assertEquals( "aa", StringUtil.trim("aa ", ' ') ); + assertEquals( "aa", StringUtil.trim(" aa", ' ') ); + assertEquals( "", StringUtil.trim(" aa ", 'a') ); + assertEquals( "aa", StringUtil.trim("\u0010 aa ", ' ') ); + assertEquals( "aa", StringUtil.trim("\n\naa\n\t", ' ') ); + assertEquals( "aa", StringUtil.trim("\"aa\"", '\"') ); + } + + @Test + public void trimQuotesTest() { + assertEquals( "", StringUtil.trimQuotes("") ); + assertEquals( "\"", StringUtil.trimQuotes("\"") ); + assertEquals( "", StringUtil.trimQuotes("\"\"") ); + assertEquals( "\"aa", StringUtil.trimQuotes("\"aa") ); + assertEquals( "aa\"", StringUtil.trimQuotes("aa\"") ); + assertEquals( "aa", StringUtil.trimQuotes("\"aa\"") ); + } + + @Test + public void formatBytesToStringTest(){ + byte[] data = new byte[1]; + assertEquals("000 00 '. '", + StringUtil.formatBytesToString(data)); + + data[0] = 65; + assertEquals("000 41 'A '", + StringUtil.formatBytesToString(data)); + + byte[] data2 = new byte[8]; + data2[4] = 65; + assertEquals("000 00 00 00 00 41 00 00 00 '....A...'", + StringUtil.formatBytesToString(data2)); + + byte[] data3 = new byte[32]; + data3[4] = 65; + assertEquals("000 00 00 00 00 41 00 00 00 '....A...'\n"+ + "008 00 00 00 00 00 00 00 00 '........'\n"+ + "016 00 00 00 00 00 00 00 00 '........'\n"+ + "024 00 00 00 00 00 00 00 00 '........'", + StringUtil.formatBytesToString(data3)); + } + + @Test + public void joinTest(){ + assertEquals("", StringUtil.join(Arrays.asList(), ",")); + assertEquals("1,2,3,4,5", StringUtil.join(Arrays.asList(1,2,3,4,5), ",")); + assertEquals("animal,monkey,dog", StringUtil.join(Arrays.asList("animal", "monkey", "dog"), ",")); + assertEquals("12345", StringUtil.join(Arrays.asList(1,2,3,4,5), "")); + } +} diff --git a/test/zutil/algo/search/QuickSelectTest.java b/test/zutil/algo/search/QuickSelectTest.java new file mode 100755 index 00000000..b5910063 --- /dev/null +++ b/test/zutil/algo/search/QuickSelectTest.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.algo.search; + +import zutil.algo.sort.sortable.SortableIntArray; + +import java.util.Arrays; + + +/** + * TODO: Convert to JUnit + */ +public class QuickSelectTest { + public static void main(String[] args){ + int[] array = {1,3,4,6,3,2,98,5,7,8,543,2,4,5,8,9,5,2,3,5,7,5,3,2,6,8,5,324,8,6}; + //int[] array = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,17,18,19,20}; + + long time = System.currentTimeMillis(); + int median = (Integer)QuickSelect.find(new SortableIntArray(array), array.length/2); + System.out.println("QuickSelection("+(System.currentTimeMillis()-time)+"ms): "+median); + + time = System.currentTimeMillis(); + Arrays.sort(array); + System.out.println("RightAnswer("+(System.currentTimeMillis()-time)+"ms): "+array[array.length/2]); + + System.out.println("Sorted Array("+array.length+"): "); + for(int i=0; i array[i]){ + error = i; + } + } + + if(error >= 0){ + System.out.println("\nArray not sorted!! ("+array[error-1]+" > "+array[error]+")"); + } + System.out.println("\nTime: "+time+" ms"); + } +} diff --git a/test/zutil/chart/ChartTest.java b/test/zutil/chart/ChartTest.java new file mode 100755 index 00000000..7cd8e93d --- /dev/null +++ b/test/zutil/chart/ChartTest.java @@ -0,0 +1,61 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.chart; + +import zutil.log.LogUtil; + +import javax.swing.*; +import java.util.logging.Level; + + +public class ChartTest extends JFrame{ + private static final long serialVersionUID = 1L; + + public static void main(String[] args) { + LogUtil.setLevel("zutil", Level.FINEST); + ChartTest frame = new ChartTest(); + frame.setVisible(true); + } + + public ChartTest(){ + ChartData data = new ChartData(); + data.addPoint(1,1); + data.addPoint(2,1); + data.addPoint(3,1); + data.addPoint(4,1); + data.addPoint(5,1); + data.addPoint(6,1); + data.addPoint(7,1); + data.addPoint(8,1); + + LineChart chart = new LineChart(); + chart.setChartData( data ); + this.add( chart ); + + this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); + this.setSize(600, 400); + } + +} diff --git a/hal-core/src/se/hal/struct/devicedata/RadonSensorData.java b/test/zutil/db/DBConnectionTest.java old mode 100644 new mode 100755 similarity index 56% rename from hal-core/src/se/hal/struct/devicedata/RadonSensorData.java rename to test/zutil/db/DBConnectionTest.java index a44b41c6..147503b8 --- a/hal-core/src/se/hal/struct/devicedata/RadonSensorData.java +++ b/test/zutil/db/DBConnectionTest.java @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2025 Ziver Koc + * Copyright (c) 2015 Ziver Koc * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,44 +22,40 @@ * THE SOFTWARE. */ -package se.hal.struct.devicedata; +package zutil.db; -import se.hal.intf.HalSensorData; +import zutil.db.handler.SimpleSQLResult; -public class RadonSensorData extends HalSensorData { - - private double radon; +import java.sql.PreparedStatement; - public RadonSensorData(){} - public RadonSensorData(double radon, long timestamp){ - this.radon = radon; - super.setTimestamp(timestamp); - } +public class DBConnectionTest { - - @Override - public String toString(){ - return radon + " Bq/m³"; - } - - // ---------------------------------------- - // Storage methods - // ---------------------------------------- - - /** - * @return radon measurement in Bq/m3 - */ - @Override - public double getData() { - return radon; - } - - /** - * @param radon the radon measurement in Bq/m3 - */ - @Override - public void setData(double radon) { - this.radon = radon; - } + public static void main(String[] args){ + try { + DBConnection db = new DBConnection("koc.se","db","user","password"); + + // Query 1 + PreparedStatement sql = db.getPreparedStatement("SELECT ?"); + sql.setInt(1, 1); + DBConnection.exec(sql); + + // Query 2 + db.exec("UPDATE ..."); + + // Query 3 + String s = db.exec("SELECT hello", new SimpleSQLResult()); + System.out.println( s ); + + // Query 4 + PreparedStatement sql2 = db.getPreparedStatement("SELECT ?"); + sql2.setString(1, "hello"); + String s2 = DBConnection.exec(sql2, new SimpleSQLResult()); + System.out.println( s2 ); + + db.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/test/zutil/db/SQLQueryTest.java b/test/zutil/db/SQLQueryTest.java new file mode 100755 index 00000000..7adf7b5e --- /dev/null +++ b/test/zutil/db/SQLQueryTest.java @@ -0,0 +1,120 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.db; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +public class SQLQueryTest { + + @Test + public void selectTest() { + assertEquals( "SELECT * FROM test1", + ""+SQLQuery.SELECT().FROM("test1") ); + assertEquals( "SELECT * FROM test1", + ""+SQLQuery.SELECT("*").FROM("test1") ); + assertEquals( "SELECT test1,test2 FROM test1", + ""+SQLQuery.SELECT("test1","test2").FROM("test1") ); + } + @Test + public void selectJoinTest() { + assertEquals( "SELECT * FROM test1 JOIN test2", + ""+SQLQuery.SELECT("*").FROM("test1").JOIN("test2") ); + assertEquals( "SELECT * FROM test1 NATURAL JOIN test2", + ""+SQLQuery.SELECT("*").FROM("test1").NATURAL_JOIN("test2") ); + assertEquals( "SELECT * FROM test1 UNION test2", + ""+SQLQuery.SELECT("*").FROM("test1").UNION("test2") ); + assertEquals( "SELECT * FROM test1 JOIN test2 NATURAL JOIN test3 UNION test4", + ""+SQLQuery.SELECT("*").FROM("test1").JOIN("test2").NATURAL_JOIN("test3").UNION("test4") ); + + assertEquals( "SELECT * FROM test1 NATURAL JOIN test2 NATURAL JOIN test3 NATURAL JOIN test4", + ""+SQLQuery.SELECT("*").FROM().NATURAL_JOIN("test1","test2","test3","test4") ); + assertEquals( "SELECT * FROM test1 JOIN test2 JOIN test3 JOIN test4", + ""+SQLQuery.SELECT("*").FROM().JOIN("test1","test2","test3","test4") ); + assertEquals( "SELECT * FROM test1 UNION test2 UNION test3 UNION test4", + ""+SQLQuery.SELECT("*").FROM().UNION("test1","test2","test3","test4") ); + } + @Test + public void selectWhereTest() { + assertEquals( "SELECT * FROM test1 WHERE arg=value", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value") ); + } + @Test + public void selectGroupByTest() { + assertEquals( "SELECT * FROM test1 GROUP BY col1", + ""+SQLQuery.SELECT("*").FROM("test1").GROUP_BY("col1") ); + assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1") ); + assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ASC", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ASC() ); + assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 DESC", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").DESC() ); + } + @Test + public void selectOrderByTest() { + assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1") ); + assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1 ASC", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1").ASC() ); + assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1 DESC", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1").DESC() ); + assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ORDER BY col2 DESC", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ORDER_BY("col2").DESC() ); + assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ASC ORDER BY col2 DESC", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ASC().ORDER_BY("col2").DESC() ); + } + @Test + public void selectLimitTest() { + assertEquals( "SELECT * FROM test1 LIMIT 1", + ""+SQLQuery.SELECT("*").FROM("test1").LIMIT(1) ); + assertEquals( "SELECT * FROM test1 LIMIT 1 4", + ""+SQLQuery.SELECT("*").FROM("test1").LIMIT(1).TO(4) ); + assertEquals( "SELECT * FROM test1 WHERE arg=value LIMIT 1", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").LIMIT(1) ); + assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1 DESC LIMIT 1", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1").DESC().LIMIT(1) ); + assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ORDER BY col2 DESC LIMIT 1", + ""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ORDER_BY("col2").DESC().LIMIT(1) ); + } + + + @Test + public void updateTest() { + + } + + + @Test + public void deleteTest() { + + } + + @Test + public void createTest() { + + } +} diff --git a/test/zutil/image/ImageProcessorTest.java b/test/zutil/image/ImageProcessorTest.java new file mode 100755 index 00000000..1b1ea84b --- /dev/null +++ b/test/zutil/image/ImageProcessorTest.java @@ -0,0 +1,130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.image; + +import zutil.ProgressListener; +import zutil.image.filter.GaussianBlurFilter; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + + +@SuppressWarnings({ "unused", "rawtypes" }) +public class ImageProcessorTest implements ProgressListener{ + private static String imgPath = "test.gif"; + //private static String imgPath = "test2.jpg"; + + private JLabel processedLabel; + private JLabel orginalLabel; + private JProgressBar progress; + + public static void main(String[] args){ + new ImageProcessorTest(); + } + + @SuppressWarnings("unchecked") + public ImageProcessorTest(){ + JFrame frame = getJFrame(); + BufferedImage img = null; + + try { + // Read from an input stream + InputStream is = new BufferedInputStream(new FileInputStream(imgPath)); + img = ImageIO.read(is); + } catch (IOException e) { + e.printStackTrace(); + System.exit(1); + } + + ImageIcon orginalIcon = new ImageIcon(img); + orginalLabel.setIcon(orginalIcon); + frame.setVisible(true); + frame.pack(); + + BufferedImage procImg = null; + try { + //ImageFilterProcessor processor = new SobelEdgeDetectionFilter(img); + ImageFilterProcessor processor = new GaussianBlurFilter(img); + //ImageFilterProcessor processor = new BlurFilter(img, 100); + //ImageFilterProcessor processor = new ColorIntensityFilter(img, true); + //ImageFilterProcessor processor = new ContrastBrightnessFilter(img); + //ImageFilterProcessor processor = new DitheringFilter(img); + //ImageFilterProcessor processor = new MeanBlurFilter(img); + //ImageFilterProcessor processor = new MedianFilter(img); + //ImageFilterProcessor processor = new ResizeImage(img,100,100); + //ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100); + + processor.setProgressListener(this); + procImg = processor.process(); + } catch (Exception e) { + e.printStackTrace(); + } + ImageIcon processedIcon = new ImageIcon(procImg); + processedLabel.setIcon(processedIcon); + + + frame.pack(); + } + + private JFrame getJFrame() { + processedLabel = new JLabel("Processed"); + orginalLabel = new JLabel("Orginal"); + + progress = new JProgressBar(); + progress.setMaximum(100); + progress.setValue(0); + progress.setIndeterminate(false); + progress.setStringPainted(true); + + JPanel jPanel = new JPanel(); + jPanel.setLayout(new BorderLayout()); + jPanel.add(orginalLabel, BorderLayout.NORTH); + jPanel.add(processedLabel, BorderLayout.CENTER); + jPanel.add(progress, BorderLayout.SOUTH); + + JFrame jFrame = new JFrame("ImageProcessorTest"); + jFrame.setSize(new Dimension(715, 361)); + jFrame.setContentPane(jPanel); + jFrame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + return jFrame; + } + + public void progressUpdate(Object source, Object info, double percent) { + progress.setValue((int)percent); + } +} diff --git a/test/zutil/io/BoundaryBufferedInputStreamTest.java b/test/zutil/io/BoundaryBufferedInputStreamTest.java new file mode 100755 index 00000000..c092adc4 --- /dev/null +++ b/test/zutil/io/BoundaryBufferedInputStreamTest.java @@ -0,0 +1,99 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.io; + +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + + +@SuppressWarnings("resource") +public class BoundaryBufferedInputStreamTest { + + @Test + public void testReadB1() throws IOException { + StringInputStream inin = new StringInputStream(); + BoundaryBufferedInputStream in = new BoundaryBufferedInputStream(inin); + inin.add("aaa#aaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaa#"); + + in.setBoundary("#"); + + int n = 0; + for(n=0; in.read() != -1; n++); + assertEquals(3, n); + + in.next(); + n = 0; + for(n=0; in.read() != -1; n++); + assertEquals(16, n); + + in.next(); + n = 0; + for(n=0; in.read() != -1; n++); + assertEquals(15, n); + + in.next(); + assertEquals(-1, in.read()); + + } + + @Test + public void testOnlyBoundaries() throws IOException { + StringInputStream inin = new StringInputStream(); + BoundaryBufferedInputStream in = new BoundaryBufferedInputStream(inin); + inin.add("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + in.setBoundary("a"); + + int n; + for(n=1; true; n++){ + assertEquals(-1, in.read()); + assertEquals(-1, in.read()); + in.next(); + if(!in.isBoundary()) + break; + } + assertEquals(35, n); + } + + @Test + public void testNoBounds() throws IOException { + String data = "1234567891011121314151617181920"; + StringInputStream inin = new StringInputStream(); + BoundaryBufferedInputStream in = new BoundaryBufferedInputStream(inin); + inin.add(data); + in.setBoundary("#"); + + int out; + StringBuilder output = new StringBuilder(); + while((out = in.read()) != -1){ + output.append((char)out); + } + assertEquals(data, output.toString()); + } + +} diff --git a/test/zutil/io/DynamicByteArrayStreamTest.java b/test/zutil/io/DynamicByteArrayStreamTest.java new file mode 100755 index 00000000..842b1a42 --- /dev/null +++ b/test/zutil/io/DynamicByteArrayStreamTest.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.io; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +/** + * User: Ziver + */ +public class DynamicByteArrayStreamTest { + + @Test + public void emptyArray(){ + DynamicByteArrayStream out = new DynamicByteArrayStream(); + assertEquals(0, out.available()); + assertEquals(0, out.getBytes().length); + assertTrue(out.toString().isEmpty()); + } + + @Test + public void oneByteArray(){ + byte[] b = new byte[]{0x01,0x02,0x03,0x04}; + + DynamicByteArrayStream out = new DynamicByteArrayStream(); + out.append(b); + + byte[] result = out.getBytes(); + for(int i=0; i + + + + + + + + +
    + + + +
      +
    • +
      + + Test + +
      +
    • +
    + + \ No newline at end of file diff --git a/test/zutil/log/net/NetLogServerTest.java b/test/zutil/log/net/NetLogServerTest.java new file mode 100755 index 00000000..823ab964 --- /dev/null +++ b/test/zutil/log/net/NetLogServerTest.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.log.net; + +import zutil.log.LogUtil; + +import java.util.logging.Level; +import java.util.logging.Logger; + + +public class NetLogServerTest { + private static final Logger logger = LogUtil.getLogger(); + + public static void main(String[] args){ + LogUtil.setGlobalLevel(Level.FINEST); + LogUtil.addGlobalHandler(new NetLogServer(5050)); + + while(true){ + logger.log(Level.SEVERE, "Test Severe"); + logger.log(Level.WARNING, "Test Warning"); + logger.log(Level.INFO, "Test Info"); + logger.log(Level.FINE, "Test Fine"); + logger.log(Level.FINER, "Test Finer"); + logger.log(Level.FINEST, "Test Finest"); + + logger.log(Level.SEVERE, "Test Exception", new Exception("Test")); + + try{Thread.sleep(3000);}catch(Exception e){} + } + } +} diff --git a/test/zutil/net/ServerFindClientTest.java b/test/zutil/net/ServerFindClientTest.java new file mode 100755 index 00000000..ff04d09d --- /dev/null +++ b/test/zutil/net/ServerFindClientTest.java @@ -0,0 +1,41 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +import zutil.net.ServerFindClient; + +import java.io.IOException; + + +public class ServerFindClientTest { + public static void main(String[] args){ + try { + ServerFindClient client = new ServerFindClient(2000); + System.out.println(client.find().getHostAddress()); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/test/zutil/net/ServerFindServerTest.java b/test/zutil/net/ServerFindServerTest.java new file mode 100755 index 00000000..19bffc5a --- /dev/null +++ b/test/zutil/net/ServerFindServerTest.java @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net; + +import java.io.IOException; + + +public class ServerFindServerTest { + public static void main(String[] args){ + try { + new ServerFind(2000); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/test/zutil/net/http/HTTPGuessTheNumber.java b/test/zutil/net/http/HTTPGuessTheNumber.java new file mode 100755 index 00000000..2b509c64 --- /dev/null +++ b/test/zutil/net/http/HTTPGuessTheNumber.java @@ -0,0 +1,102 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import java.io.IOException; +import java.util.Map; + + +public class HTTPGuessTheNumber implements HttpPage{ + + public static void main(String[] args) throws IOException{ + //HttpServer server = new HttpServer("localhost", 443, FileFinder.find("keySSL"), "rootroot");//SSL + HttpServer server = new HttpServer(8080); + server.setDefaultPage(new HTTPGuessTheNumber()); + server.run(); + } + + public void respond(HttpPrintStream out, + HttpHeader client_info, + Map session, + Map cookie, + Map request) throws IOException { + + out.enableBuffering(true); + out.println(""); + out.println("

    Welcome To The Number Guess Game!

    "); + + if(session.containsKey("random_nummber") && request.containsKey("guess") && !request.get("guess").isEmpty()){ + int guess = Integer.parseInt(request.get("guess")); + int nummber = (Integer)session.get("random_nummber"); + try { + if(guess == nummber){ + session.remove("random_nummber"); + out.println("You Guessed Right! Congrats!"); + out.println(""); + return; + } + else if(guess > nummber){ + out.println("To High
    "); + if(Integer.parseInt(cookie.get("high")) > guess){ + out.setCookie("high", ""+guess); + cookie.put("high", ""+guess); + } + } + else{ + out.println("To Low
    "); + if(Integer.parseInt(cookie.get("low")) < guess){ + out.setCookie("low", ""+guess); + cookie.put("low", ""+guess); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + else{ + session.put("random_nummber", (int)(Math.random()*99+1)); + try { + out.setCookie("low", "0"); + out.setCookie("high", "100"); + cookie.put("low", "0"); + cookie.put("high", "100"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + out.println("
    "); + out.println(cookie.get("low")+" < X < "+cookie.get("high")+"
    "); + out.println("Guess a number between 0 and 100:
    "); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println("DEBUG: nummber="+session.get("random_nummber")+"
    "); + out.println(""); + } + +} diff --git a/test/zutil/net/http/HTTPUploaderTest.java b/test/zutil/net/http/HTTPUploaderTest.java new file mode 100755 index 00000000..601957eb --- /dev/null +++ b/test/zutil/net/http/HTTPUploaderTest.java @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import java.io.IOException; +import java.util.Map; + + +public class HTTPUploaderTest implements HttpPage{ + + public static void main(String[] args) throws IOException{ + HttpServer server = new HttpServer(80); + server.setDefaultPage(new HTTPUploaderTest()); + server.run(); + } + + public void respond(HttpPrintStream out, + HttpHeader client_info, + Map session, + Map cookie, + Map request) throws IOException { + + if(!session.containsKey("file1")){ + out.println("" + + "
    " + + "

    Please specify a file, or a set of files:
    " + + " " + + "

    " + + " " + + " " + + ""); + } + } + +} diff --git a/test/zutil/net/http/HttpURLTest.java b/test/zutil/net/http/HttpURLTest.java new file mode 100755 index 00000000..6e71dc80 --- /dev/null +++ b/test/zutil/net/http/HttpURLTest.java @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.http; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + + +public class HttpURLTest { + + @Test + public void fullURLTest() { + HttpURL url = new HttpURL(); + url.setProtocol("http"); + assertEquals( "http://127.0.0.1/", url.getURL() ); + + url.setHost("koc.se"); + assertEquals( "http://koc.se/", url.getURL() ); + + url.setPort( 80 ); + assertEquals( "http://koc.se:80/", url.getURL() ); + + url.setPath("test/index.html"); + assertEquals( "http://koc.se:80/test/index.html", url.getURL() ); + + url.setParameter("key", "value"); + assertEquals( "http://koc.se:80/test/index.html?key=value", url.getURL() ); + + url.setAnchor( "anch" ); + assertEquals( "http://koc.se:80/test/index.html?key=value#anch", url.getURL() ); + } + + @Test + public void urlParameterTest() { + HttpURL url = new HttpURL(); + url.setParameter("key1", "value1"); + assertEquals( "key1=value1", url.getParameterString() ); + + url.setParameter("key1", "value1"); + assertEquals( "key1=value1", url.getParameterString() ); + + url.setParameter("key2", "value2"); + assertThat(url.getParameterString(), allOf(containsString("key2=value2"), containsString("key1=value1"))); + + } + + +} diff --git a/hal-core/src/se/hal/struct/PluginConfig.java b/test/zutil/net/nio/NetworkClientTest.java old mode 100644 new mode 100755 similarity index 51% rename from hal-core/src/se/hal/struct/PluginConfig.java rename to test/zutil/net/nio/NetworkClientTest.java index 1be7a297..e99d145a --- a/hal-core/src/se/hal/struct/PluginConfig.java +++ b/test/zutil/net/nio/NetworkClientTest.java @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Ziver Koc + * Copyright (c) 2015 Ziver Koc * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,47 +22,38 @@ * THE SOFTWARE. */ -package se.hal.struct; +package zutil.net.nio; -import zutil.db.DBConnection; -import zutil.db.bean.DBBean; -import zutil.db.bean.DBBeanSQLResultHandler; +import zutil.net.nio.message.StringMessage; +import zutil.net.nio.response.PrintRsp; -import java.sql.PreparedStatement; -import java.sql.SQLException; +import java.io.IOException; +import java.net.InetAddress; +import java.security.NoSuchAlgorithmException; -@DBBean.DBTable(value="plugin") -public class PluginConfig extends DBBean { - private String name; - private boolean enabled; - - - /** - * @return a PluginConfig bean for the specific plugin name. - */ - public static PluginConfig getPluginConfig(DBConnection db, String name) throws SQLException { - PreparedStatement stmt = db.getPreparedStatement( "SELECT plugin.* FROM plugin WHERE name == ?" ); - stmt.setString(1, name); - return DBConnection.exec(stmt, DBBeanSQLResultHandler.create(PluginConfig.class, db)); - } - - - public PluginConfig() {} - public PluginConfig(String name) { - this.name = name; - } - - - public String getName() { - return name; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } +@SuppressWarnings("unused") +public class NetworkClientTest { + public static void main(String[] args) throws NoSuchAlgorithmException { + try { + int count = 0; + long time = System.currentTimeMillis()+1000*60; + NioClient client = new NioClient(InetAddress.getByName("localhost"), 6056); + //client.setEncrypter(new Encrypter("lol", Encrypter.PASSPHRASE_DES_ALGO)); + while(time > System.currentTimeMillis()){ + PrintRsp handler = new PrintRsp(); + client.send(handler, new StringMessage("StringMessage: "+count)); + handler.waitForResponse(); + //try {Thread.sleep(100);} catch (InterruptedException e) {} + //System.out.println("sending.."); + count++; + } + + System.out.println("Message Count 1m: "+count); + System.out.println("Message Count 1s: "+count/60); + System.exit(0); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/test/zutil/net/nio/NetworkServerTest.java b/test/zutil/net/nio/NetworkServerTest.java new file mode 100755 index 00000000..b987acdf --- /dev/null +++ b/test/zutil/net/nio/NetworkServerTest.java @@ -0,0 +1,41 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.nio; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; + + +@SuppressWarnings("unused") +public class NetworkServerTest { + public static void main(String[] args) throws NoSuchAlgorithmException { + try { + NioServer server = new NioServer(6056); + //server.setEncrypter(new Encrypter("lol", Encrypter.PASSPHRASE_DES_ALGO)); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/test/zutil/net/ssdp/SSDPClientTest.java b/test/zutil/net/ssdp/SSDPClientTest.java new file mode 100755 index 00000000..15828cd7 --- /dev/null +++ b/test/zutil/net/ssdp/SSDPClientTest.java @@ -0,0 +1,52 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ssdp; + +import zutil.log.LogUtil; +import zutil.net.ssdp.SSDPClient; + +import java.io.IOException; +import java.util.logging.Level; + + +/** + * Created by Ziver on 2015-09-29. + */ +public class SSDPClientTest { + + public static void main(String[] args) throws IOException { + System.out.println(LogUtil.getCallingClass()); + LogUtil.setGlobalLevel(Level.FINEST); + SSDPClient ssdp = new SSDPClient(); + ssdp.requestService("upnp:rootdevice"); + ssdp.start(); + + for(int i=0; true ;++i){ + while( i==ssdp.getServicesCount("upnp:rootdevice") ){ try{Thread.sleep(100);}catch(Exception e){} } + System.out.println("************************" ); + System.out.println("" + ssdp.getServices("upnp:rootdevice").get(i)); + } + } +} diff --git a/plugins/hal-zwave/test/se/hal/plugin/zwave/HalZWaveControllerTest.java b/test/zutil/net/ssdp/SSDPServerTest.java old mode 100644 new mode 100755 similarity index 69% rename from plugins/hal-zwave/test/se/hal/plugin/zwave/HalZWaveControllerTest.java rename to test/zutil/net/ssdp/SSDPServerTest.java index 243a79b9..d8f85a94 --- a/plugins/hal-zwave/test/se/hal/plugin/zwave/HalZWaveControllerTest.java +++ b/test/zutil/net/ssdp/SSDPServerTest.java @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2025 Ziver Koc + * Copyright (c) 2015 Ziver Koc * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,30 +22,32 @@ * THE SOFTWARE. */ -package se.hal.plugin.zwave; +package zutil.net.ssdp; -import zutil.log.CompactLogFormatter; import zutil.log.LogUtil; import java.io.IOException; import java.util.logging.Level; + /** - * @author zagumennikov + * Created by Ziver on 2015-09-29. */ -public class HalZWaveControllerTest { +public class SSDPServerTest { public static void main(String[] args) throws IOException { - LogUtil.setGlobalFormatter(new CompactLogFormatter()); - LogUtil.setGlobalLevel(Level.ALL); + LogUtil.setGlobalLevel(Level.FINEST); - HalZWaveController controller = new HalZWaveController(); - controller.initialize( - "/dev/serial/by-id/usb-0658_0200-if00"); + StandardSSDPInfo service = new StandardSSDPInfo(); + service.setLocation("nowhere"); + service.setST("zep:discover"); + service.setHeader("Alias", "Desktop"); + service.setHeader("PublicKey", "SuperDesktopKey"); - System.out.println("Press ENTER to exit application."); - System.in.read(); - controller.close(); + SSDPServer ssdp = new SSDPServer(); + ssdp.addService(service); + ssdp.start(); + System.out.println("SSDP Server running"); } } diff --git a/test/zutil/net/update/UpdateClientTest.java b/test/zutil/net/update/UpdateClientTest.java new file mode 100755 index 00000000..37b5a755 --- /dev/null +++ b/test/zutil/net/update/UpdateClientTest.java @@ -0,0 +1,73 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import zutil.ProgressListener; +import zutil.log.CompactLogFormatter; +import zutil.log.LogUtil; + +import java.awt.*; +import java.util.logging.Level; + + +public class UpdateClientTest implements ProgressListener{ + public static void main(String[] args){ + LogUtil.setLevel("zutil", Level.FINEST); + LogUtil.setFormatter("zutil", new CompactLogFormatter()); + + UpdateClientTest client = new UpdateClientTest(); + client.start(); + } + + public void start(){ + try { + final UpdateClient client = new UpdateClient("localhost", 2000, "C:\\Users\\Ziver\\Desktop\\client"); + client.setProgressListener(new Zupdater()); + + //client.setProgressListener(this); + + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + Zupdater gui = new Zupdater(); + client.setProgressListener(gui); + gui.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + client.update(); + client.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void progressUpdate(UpdateClient source, FileInfo info, double percent) { + System.out.println(info+": "+percent+"%"); + } +} diff --git a/test/zutil/net/update/UpdateServerTest.java b/test/zutil/net/update/UpdateServerTest.java new file mode 100755 index 00000000..6065606b --- /dev/null +++ b/test/zutil/net/update/UpdateServerTest.java @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.update; + +import zutil.log.CompactLogFormatter; +import zutil.log.LogUtil; + +import java.util.logging.Level; + + +public class UpdateServerTest { + public static void main(String[] args){ + try { + LogUtil.setGlobalLevel(Level.FINEST); + LogUtil.setGlobalFormatter(new CompactLogFormatter()); + + new UpdateServer(2000, "C:\\Users\\Ziver\\Desktop\\server"); + }catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/zutil/net/upnp/UPnPServerTest.java b/test/zutil/net/upnp/UPnPServerTest.java new file mode 100755 index 00000000..94fef659 --- /dev/null +++ b/test/zutil/net/upnp/UPnPServerTest.java @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.upnp; + +import zutil.io.MultiPrintStream; +import zutil.net.http.HttpServer; +import zutil.net.ssdp.SSDPServer; +import zutil.net.upnp.service.UPnPContentDirectory; +import zutil.net.ws.WebServiceDef; +import zutil.net.ws.soap.SOAPHttpPage; + +import java.io.File; +import java.io.IOException; + + +public class UPnPServerTest { + + public static void main(String[] args) throws IOException{ + UPnPMediaServer upnp = new UPnPMediaServer("http://192.168.0.60:8080/"); + MultiPrintStream.out.println("UPNP Server running"); + + UPnPContentDirectory cds = new UPnPContentDirectory(new File("C:\\Users\\Ziver\\Desktop\\lan")); + WebServiceDef ws = new WebServiceDef( UPnPContentDirectory.class ); + + HttpServer http = new HttpServer(8080); + //http.setDefaultPage(upnp); + http.setPage("/RootDesc", upnp ); + http.setPage("/SCP/ContentDir", cds ); + SOAPHttpPage soap = new SOAPHttpPage(ws); + soap.setObject( cds ); + soap.enableSession( false ); + http.setPage("/Action/ContentDir", soap ); + http.start(); + MultiPrintStream.out.println("HTTP Server running"); + + SSDPServer ssdp = new SSDPServer(); + ssdp.addService( upnp ); + ssdp.start(); + MultiPrintStream.out.println("SSDP Server running"); + } +} diff --git a/test/zutil/net/ws/soap/SOAPClientTest.java b/test/zutil/net/ws/soap/SOAPClientTest.java new file mode 100755 index 00000000..28bd7223 --- /dev/null +++ b/test/zutil/net/ws/soap/SOAPClientTest.java @@ -0,0 +1,55 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws.soap; + +import zutil.log.CompactLogFormatter; +import zutil.log.LogUtil; +import zutil.net.ws.WSInterface; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.logging.Level; + + +// TODO: COnvert to JUnit +public class SOAPClientTest { + + public static void main(String[] args) throws InstantiationException, IllegalAccessException, MalformedURLException { + LogUtil.setGlobalLevel(Level.ALL); + LogUtil.setFormatter("", new CompactLogFormatter()); + + TestClient intf = SOAPClientFactory.createClient(new URL("http://localhost:3289"), TestClient.class); + intf.m(); + intf.c(); + } + + + public interface TestClient extends WSInterface{ + public void m(); + + public void c(); + + } +} diff --git a/test/zutil/net/ws/soap/SOAPTest.java b/test/zutil/net/ws/soap/SOAPTest.java new file mode 100755 index 00000000..7a815c55 --- /dev/null +++ b/test/zutil/net/ws/soap/SOAPTest.java @@ -0,0 +1,157 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.net.ws.soap; + +import org.dom4j.Document; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +import zutil.net.ws.WSInterface; +import zutil.net.ws.WSInterface.WSNamespace; +import zutil.net.ws.WSReturnObject; +import zutil.net.ws.WebServiceDef; +import zutil.parser.wsdl.WSDLWriter; + + +// TODO: Convert to JUnit +public class SOAPTest { + /************************* TEST CASES ************************/ + public static void main(String[] args){ + new SOAPTest(); + } + + public SOAPTest(){ + WebServiceDef wsDef = new WebServiceDef( MainSOAPClass.class ); + SOAPHttpPage soap = new SOAPHttpPage( wsDef ); + + System.out.println( "****************** WSDL *********************" ); + WSDLWriter wsdl = new WSDLWriter( wsDef ); + wsdl.write(System.out); + + // Response + try { + System.out.println( "\n****************** REQUEST *********************" ); + String request = "\n" + + "\n" + + " \n" + + " \n" + + " IBM\n" + + " \n" + + + " \n" + + " IBM\n" + + " \n" + + " \n" + + ""; + System.out.println(request); + System.out.println( "\n****************** EXECUTION *********************" ); + Document document = soap.genSOAPResponse(request); + System.out.println( "\n****************** RESPONSE *********************" ); + + OutputFormat format = OutputFormat.createPrettyPrint(); + XMLWriter writer = new XMLWriter( System.out, format ); + writer.write( document ); + + System.out.println(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /************************* TEST CLASSES ************************/ + @SuppressWarnings("unused") + public static class SpecialReturnClass extends WSReturnObject{ + @WSValueName(value="otherValue1") + public String param1 = "otherValue1"; + @WSValueName("otherValue2") + public String param2 = "otherValue2"; + public byte[] b = new byte[]{0x12, 0x23}; + public InnerClass inner = new InnerClass(); + } + + @SuppressWarnings("unused") + public static class InnerClass extends WSReturnObject{ + public String innerClassParam1 = "innerClass1"; + public String innerClassParam2 = "innerClass2"; + } + + @SuppressWarnings("unused") + public static class SimpleReturnClass extends WSReturnObject{ + @WSValueName("otherParam1") + public String param1 = "param1"; + public String param2 = "param2"; + } + + @SuppressWarnings("unused") + @WSNamespace("http://test.se:8080/") + public static class MainSOAPClass implements WSInterface{ + public MainSOAPClass(){} + + @WSHeader() + @WSDocumentation("Documentation of method exceptionMethod()") + public void exceptionMethod( + @WSParamName(value="otherParam1", optional=true) int param1, + @WSParamName(value="otherParam2", optional=true) int param2) throws Exception{ + System.out.println("Executing method: exceptionMethod(int param1="+param1+", int param2="+param2+",)"); + throw new Exception("This is an Exception"); + } + + @WSReturnName("stringArray") + @WSParamDocumentation("Documentation of stringArrayMethod()") + public String[][] stringArrayMethod ( + @WSParamName("StringName") String str) throws Exception{ + System.out.println("Executing method: stringArrayMethod(String str='"+str+"')"); + return new String[][]{{"test","test2"},{"test3","test4"}}; + } + + @WSReturnName("specialReturnClass") + @WSParamDocumentation("Documentation of specialReturnMethod()") + public SpecialReturnClass[] specialReturnMethod ( + @WSParamName("StringName2") String str) throws Exception{ + System.out.println("Executing method: specialReturnMethod(String str='"+str+"')"); + return new SpecialReturnClass[]{new SpecialReturnClass(), new SpecialReturnClass()}; + } + + @WSReturnName("SimpleReturnClass") + @WSParamDocumentation("null is the kala") + public SimpleReturnClass simpleReturnClassMethod ( + @WSParamName("byte") String lol) throws Exception{ + System.out.println("Executing method: simpleReturnClassMethod()"); + SimpleReturnClass tmp = new SimpleReturnClass(); + tmp.param1 = "newParam1"; + tmp.param2 = "newParam2"; + return tmp; + } + + @WSParamDocumentation("void method documentation") + public void voidMethod (){ } + + @WSDisabled() + public void disabledMethod(){ } + protected void protectedMethod(){ } + + private void privateMethod(){ } + } +} diff --git a/test/zutil/parser/BBCodeParserTest.java b/test/zutil/parser/BBCodeParserTest.java new file mode 100755 index 00000000..6b5d20d0 --- /dev/null +++ b/test/zutil/parser/BBCodeParserTest.java @@ -0,0 +1,48 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +public class BBCodeParserTest{ + + @Test + public void BBCodeParser() { + BBCodeParser parser = new BBCodeParser(); + + assertEquals("1234", parser.read("1234")); + assertEquals("1234", parser.read("[i]1234[/i]")); + assertEquals("[apa]lol[/apa]", parser.read("[apa]lol[/apa]")); + assertEquals("jshdkj lol [apa]lol[/apa]", parser.read("jshdkj [u]lol [apa]lol[/apa]")); + //assertEquals("jshdkj [m]lol[/k] lol", parser.read("jshdkj [m]lol[/k] [i]lol[/i]")); + assertEquals("jshdkj [m", parser.read("jshdkj [m")); + assertEquals("jshdkj [/m", parser.read("jshdkj [/m")); + assertEquals("jshdkj m]", parser.read("jshdkj m]")); + assertEquals("jshdkj
    ", parser.read("jshdkj
    ")); + } +} diff --git a/test/zutil/parser/Base64Test.java b/test/zutil/parser/Base64Test.java new file mode 100755 index 00000000..1d2d3e92 --- /dev/null +++ b/test/zutil/parser/Base64Test.java @@ -0,0 +1,76 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import org.junit.Test; + +import java.util.Base64; + +import static org.junit.Assert.assertEquals; + + +public class Base64Test { + + @Test + public void decode() { + assertEquals( "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.", + Base64Decoder.decode("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=") + ); + + Base64Decoder decoder = new Base64Decoder(); + decoder.clear(); + decoder.read("YW55IGNhcm5hbCBwbGVhc3VyZQ=="); + assertEquals( "any carnal pleasure", decoder.toString() ); + decoder.clear(); + decoder.read("bGVhc3VyZS4="); + assertEquals( "leasure.", decoder.toString() ); + decoder.clear(); + decoder.read("YW55IGNhcm5hbCBwbGVhc3Vy"); + assertEquals( "any carnal pleasur", decoder.toString() ); + decoder.clear(); + } + + @Test + public void encode() { + assertEquals("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" , + Base64Encoder.encode("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.") + ); + + assertEquals("YW55IGNhcm5hbCBwbGVhc3VyZQ==", Base64Encoder.encode("any carnal pleasure")); + assertEquals("bGVhc3VyZS4=", Base64Encoder.encode("leasure.")); + assertEquals("YW55IGNhcm5hbCBwbGVhc3Vy", Base64Encoder.encode("any carnal pleasur")); + } + + @Test + public void encodeJavaUtil() { + assertEquals("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" , + Base64.getEncoder().encodeToString("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.".getBytes()) + ); + + assertEquals("YW55IGNhcm5hbCBwbGVhc3VyZQ==", Base64.getEncoder().encodeToString("any carnal pleasure".getBytes())); + assertEquals("bGVhc3VyZS4=", Base64.getEncoder().encodeToString("leasure.".getBytes())); + assertEquals("YW55IGNhcm5hbCBwbGVhc3Vy", Base64.getEncoder().encodeToString("any carnal pleasur".getBytes())); + } +} diff --git a/test/zutil/parser/CSVParserTest.java b/test/zutil/parser/CSVParserTest.java new file mode 100755 index 00000000..42bfdf22 --- /dev/null +++ b/test/zutil/parser/CSVParserTest.java @@ -0,0 +1,109 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import org.junit.Test; + +import java.io.IOException; +import java.io.StringReader; + +import static org.junit.Assert.assertEquals; + + +/** + * Created by ezivkoc on 2015-07-30. + */ +public class CSVParserTest { + + + @Test + public void emptyTest(){ + DataNode node = CSVParser.read(""); + assertEquals(null, node); + } + + @Test + public void simpleTest(){ + DataNode node = CSVParser.read("hello,world,you"); + assertEquals(3, node.size()); + assertEquals("hello", node.get(0).getString()); + assertEquals("world", node.get(1).getString()); + assertEquals("you", node.get(2).getString()); + } + + @Test + public void simpleHeaderTest() throws IOException { + CSVParser parser = new CSVParser(new StringReader("where,what,who\nhello,world,you"), true); + DataNode node = parser.read(); + assertEquals(3, node.size()); + assertEquals("hello", node.get(0).getString()); + assertEquals("world", node.get(1).getString()); + assertEquals("you", node.get(2).getString()); + node = parser.getHeaders(); + assertEquals("where", node.get(0).getString()); + assertEquals("what", node.get(1).getString()); + assertEquals("who", node.get(2).getString()); + } + + @Test + public void simpleMultilineTest() throws IOException { + CSVParser parser = new CSVParser( + new StringReader("hello,world,you\nhello,world,you\nhello,world,you")); + int rows=0; + for(DataNode node = parser.read(); node != null; node=parser.read(), ++rows) { + assertEquals(3, node.size()); + assertEquals("hello", node.get(0).getString()); + assertEquals("world", node.get(1).getString()); + assertEquals("you", node.get(2).getString()); + } + assertEquals(3, rows); + } + + @Test + public void quotedTest(){ + DataNode node = CSVParser.read("\"hello\",\"world\",\"you\""); + assertEquals(3, node.size()); + assertEquals("hello", node.get(0).getString()); + assertEquals("world", node.get(1).getString()); + assertEquals("you", node.get(2).getString()); + } + + @Test + public void quotedIncorrectlyTest(){ + DataNode node = CSVParser.read("hello\",wo\"rl\"d,\"you\""); + assertEquals(3, node.size()); + assertEquals("hello\"", node.get(0).getString()); + assertEquals("wo\"rl\"d", node.get(1).getString()); + assertEquals("you", node.get(2).getString()); + } + + @Test + public void quotedCommaTest(){ + DataNode node = CSVParser.read("hello,\"world,you\""); + assertEquals(2, node.size()); + assertEquals("hello", node.get(0).getString()); + assertEquals("world,you", node.get(1).getString()); + } +} diff --git a/test/zutil/parser/TemplatorTest.java b/test/zutil/parser/TemplatorTest.java new file mode 100755 index 00000000..30a171ca --- /dev/null +++ b/test/zutil/parser/TemplatorTest.java @@ -0,0 +1,305 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + + +/** + * Created by Ziver on 2015-03-23. + */ +public class TemplatorTest { + class TestClass{ + public String attr; + } + class TestSubClass extends TestClass{ + public String subAttr; + } + class TestFuncClass{ + public boolean isTrue(){ + return true; + } + public boolean isFalse(){ + return false; + } + } + + + @Test + public void tagIncorrectTest(){ + assertEquals("{{", + new Templator("{{").compile()); + assertEquals("}}", + new Templator("}}").compile()); + assertEquals("}}", + new Templator("}}").compile()); + assertEquals("{{", + new Templator("{{").compile()); + assertEquals("{", + new Templator("{").compile()); + assertEquals("}", + new Templator("}").compile()); + assertEquals("{}", + new Templator("{}").compile()); + assertEquals("{test}", + new Templator("{test}").compile()); + } + @Test + public void attributeEmptyTest(){ + Templator tmpl = new Templator("{{test}}"); + assertEquals("null", tmpl.compile()); + } + @Test + public void attributeSimpleTest() { + Templator tmpl = new Templator("{{test}}"); + tmpl.set("test", "1234"); + assertEquals("1234", tmpl.compile()); + } + @Test + public void attributeObjectTest(){ + Templator tmpl = new Templator("{{test.attr}}"); + TestClass obj = new TestClass(); + obj.attr = "1234"; + tmpl.set("test", obj); + assertEquals("1234", tmpl.compile()); + } + + + + @Test + public void conditionIncompleteTest(){ + assertEquals("{{#key}}", + new Templator("{{#key}}").compile()); + assertEquals("{{/key}}", + new Templator("{{/key}}").compile()); + assertEquals("", + new Templator("{{#key}}{{/key}}").compile()); + assertEquals("", + new Templator("{{#key}}{{/key}}").compile()); + } + @Test + public void conditionEmptyTest(){ + Templator tmpl = new Templator( + "{{#key}}123456789{{/key}}"); + assertEquals( + "", + tmpl.compile()); + } + @Test + public void conditionSimpleTest(){ + Templator tmpl = new Templator( + "{{#key}}123456789{{/key}}"); + tmpl.set("key", "set"); + assertEquals( + "123456789", + tmpl.compile()); + } + @Test + public void conditionObjectTest(){ + Templator tmpl = new Templator("{{#test.attr}}5678{{/test.attr}}"); + TestClass obj = new TestClass(); + obj.attr = "1234"; + tmpl.set("test", obj); + assertEquals("5678", tmpl.compile()); + + tmpl.clear(); + tmpl.set("test", new TestClass()); + assertEquals("", tmpl.compile()); + } + @Test + public void conditionBooleanTest(){ + Templator tmpl = new Templator( + "{{#key}}123456789{{/key}}"); + tmpl.set("key", true); + assertEquals( + "123456789", tmpl.compile()); + + tmpl.set("key", false); + assertEquals( + "", tmpl.compile()); + } + + + + @Test + public void conditionIteratorEmptyTest(){ + Templator tmpl = new Templator("{{#list}}1234 {{.}} {{/list}}"); + tmpl.set("list", new ArrayList()); + assertEquals( + "", tmpl.compile()); + } + @Test + public void conditionIteratorTest(){ + Templator tmpl = new Templator("{{#list}}{{.}}{{/list}}"); + tmpl.set("list", Arrays.asList(1,2,3,4,5,6,7,8,9)); + assertEquals( + "123456789", tmpl.compile()); + } + @Test + public void conditionArrayTest(){ + Templator tmpl = new Templator("{{#list}}{{.}}{{/list}}"); + tmpl.set("list", new int[]{1,2,3,4,5,6,7,8,9}); + assertEquals( + "123456789", tmpl.compile()); + } + @Test + public void conditionArrayLength(){ + Templator tmpl = new Templator("{{#list.length}}run once{{/list.length}}"); + tmpl.set("list", new int[]{}); + assertEquals( + "", tmpl.compile()); + tmpl.set("list", new int[]{1}); + assertEquals( + "run once", tmpl.compile()); + tmpl.set("list", new int[]{1,2,3,4,5,6,7,8,9}); + assertEquals( + "run once", tmpl.compile()); + } + + + @Test + public void negativeConditionEmptyTest(){ + Templator tmpl = new Templator( + "{{^key}}123456789{{/key}}"); + assertEquals( + "123456789", tmpl.compile()); + } + @Test + public void negativeConditionSetTest(){ + Templator tmpl = new Templator( + "{{^key}}123456789{{/key}}"); + tmpl.set("key", "set"); + assertEquals( + "", tmpl.compile()); + } + @Test + public void negativeConditionObjectTest(){ + Templator tmpl = new Templator("{{^test.attr}}5678{{/test.attr}}"); + TestClass obj = new TestClass(); + obj.attr = "1234"; + tmpl.set("test", obj); + assertEquals("", tmpl.compile()); + + tmpl.clear(); + tmpl.set("test", new TestClass()); + assertEquals("5678", tmpl.compile()); + } + @Test + public void negativeConditionIteratorTest(){ + Templator tmpl = new Templator( + "{{^key}}123456789{{/key}}"); + tmpl.set("key", Arrays.asList(1,2,3,4,5,6,7,8,9)); + assertEquals( + "", tmpl.compile()); + } + @Test + public void negativeConditionIteratorEmptyTest(){ + Templator tmpl = new Templator( + "{{^key}}123456789{{/key}}"); + tmpl.set("key", new ArrayList()); + assertEquals( + "123456789", tmpl.compile()); + } + @Test + public void negativeConditionBooleanTest(){ + Templator tmpl = new Templator( + "{{^key}}123456789{{/key}}"); + tmpl.set("key", true); + assertEquals( + "", tmpl.compile()); + + tmpl.set("key", false); + assertEquals( + "123456789", tmpl.compile()); + } + + + + @Test + public void commentTest(){ + Templator tmpl = new Templator( + "{{! This is a comment}}"); + assertEquals( + "", tmpl.compile()); + } + + + @Test + public void functionCallTest(){ + Templator tmpl = new Templator( + "{{#obj.isTrue()}}it is true{{/obj.isTrue()}}"); + tmpl.set("obj", new TestFuncClass()); + assertEquals( + "it is true", tmpl.compile()); + + tmpl = new Templator( + "{{#obj.isFalse()}}it is true{{/obj.isFalse()}}"); + tmpl.set("obj", new TestFuncClass()); + assertEquals( + "", tmpl.compile()); + } + @Test + public void functionInArrayTest(){ + Templator tmpl = new Templator( + "{{#list}}{{#.isTrue()}}1{{/.isTrue()}}{{/list}}"); + tmpl.set("list", new TestFuncClass[]{ + new TestFuncClass(),new TestFuncClass(),new TestFuncClass() + }); + assertEquals( + "111", tmpl.compile()); + } + + + @Test + public void recursiveTemplateorTest(){ + Templator tmpl2 = new Templator( + "{{value1}},{{value2}}"); + tmpl2.set("value1", "sub1"); + tmpl2.set("value2", "sub2"); + Templator tmpl = new Templator( + "{{parent}}:{{child}}"); + tmpl.set("parent", "super"); + tmpl.set("child", tmpl2); + + assertEquals( + "super:sub1,sub2", tmpl.compile()); + } + + + @Test + public void subClassTest(){ + Templator tmpl = new Templator("{{test.attr}}:{{test.subAttr}}"); + TestSubClass obj = new TestSubClass(); + obj.attr = "1234"; + obj.subAttr = "5678"; + tmpl.set("test", obj); + assertEquals("1234:5678", tmpl.compile()); + } +} diff --git a/test/zutil/parser/URLDecoderTest.java b/test/zutil/parser/URLDecoderTest.java new file mode 100755 index 00000000..5a419c21 --- /dev/null +++ b/test/zutil/parser/URLDecoderTest.java @@ -0,0 +1,62 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser; + +import org.junit.Test; +import zutil.parser.URLDecoder; + +import java.io.UnsupportedEncodingException; + +import static org.junit.Assert.assertEquals; + + +/** + * Created by ezivkoc on 2015-12-11. + */ +public class URLDecoderTest { + + @Test + public void simpleTest(){ + assertEquals(null, URLDecoder.decode(null)); + assertEquals("", URLDecoder.decode("")); + assertEquals("space space", URLDecoder.decode("space space")); + assertEquals("space space", URLDecoder.decode("space+space")); + assertEquals("space space", URLDecoder.decode("space%20space")); + } + + @Test + public void percentTest(){ + assertEquals("test+", URLDecoder.decode("test%2B")); + assertEquals("test%2", URLDecoder.decode("test%2")); + assertEquals("test+test", URLDecoder.decode("test%2Btest")); + assertEquals("test+test", URLDecoder.decode("test%2btest")); + } + + @Test + public void percentMultibyteTest() throws UnsupportedEncodingException { + assertEquals("Ängen", java.net.URLDecoder.decode("%C3%84ngen", "UTF-8")); + assertEquals("Ängen", URLDecoder.decode("%C3%84ngen")); + } +} diff --git a/test/zutil/parser/binary/BinaryStructInputStreamTest.java b/test/zutil/parser/binary/BinaryStructInputStreamTest.java new file mode 100755 index 00000000..48237e1b --- /dev/null +++ b/test/zutil/parser/binary/BinaryStructInputStreamTest.java @@ -0,0 +1,128 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.binary; + +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; + + +/** + * Created by Ziver + */ +public class BinaryStructInputStreamTest { + interface BinaryTestStruct extends BinaryStruct{ + void assertObj(); + } + + @Test + public void basicIntTest(){ + BinaryTestStruct struct = new BinaryTestStruct() { + @BinaryField(index=1, length=32) + public int i1; + @BinaryField(index=2, length=32) + public int i2; + + public void assertObj(){ + assertEquals(1, i1); + assertEquals(2, i2); + } + }; + + BinaryStructInputStream.parse(struct, new byte[]{0,0,0,1, 0,0,0,2}); + struct.assertObj(); + } + + @Test + public void basicBooleanTest(){ + BinaryTestStruct struct = new BinaryTestStruct() { + @BinaryField(index=1, length=1) + public boolean b1; + @BinaryField(index=2, length=1) + public boolean b2; + + public void assertObj(){ + assertFalse(b1); + assertFalse(b2); + } + }; + + BinaryStructInputStream.parse(struct, new byte[]{0b0100_000}); + struct.assertObj(); + } + + @Test + public void basicStringTest(){ + BinaryTestStruct struct = new BinaryTestStruct() { + @BinaryField(index=1, length=8*12) + public String s1; + + public void assertObj(){ + assertEquals("hello world!", s1); + } + }; + + BinaryStructInputStream.parse(struct, "hello world!".getBytes()); + struct.assertObj(); + } + + @Test + public void nonLinedLength(){ + BinaryTestStruct struct = new BinaryTestStruct() { + @BinaryField(index=1, length=12) + public int i1; + @BinaryField(index=2, length=12) + public int i2; + + public void assertObj(){ + assertEquals(1, i1); + assertEquals(2048, i2); + } + }; + + BinaryStructInputStream.parse(struct, new byte[]{0b0000_0000,0b0001_1000,0b0000_0000}); + struct.assertObj(); + } + + // TODO: add full non lined length support + // @Test + public void nonLinedLength2(){ + BinaryTestStruct struct = new BinaryTestStruct() { + @BinaryField(index=1, length=12) + public int i1; + @BinaryField(index=2, length=12) + public int i2; + + public void assertObj(){ + assertEquals(17, i1); + assertEquals(2048, i2); + } + }; + + BinaryStructInputStream.parse(struct, new byte[]{0b0000_0001,0b0001_1000,0b0000_0000}); + struct.assertObj(); + } +} diff --git a/test/zutil/parser/binary/BinaryStructOutputStreamTest.java b/test/zutil/parser/binary/BinaryStructOutputStreamTest.java new file mode 100755 index 00000000..daa129ad --- /dev/null +++ b/test/zutil/parser/binary/BinaryStructOutputStreamTest.java @@ -0,0 +1,89 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.binary; + +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertArrayEquals; + + +/** + * Created by Ziver + */ +public class BinaryStructOutputStreamTest { + + @Test + public void basicIntTest() throws IOException { + BinaryStruct struct = new BinaryStruct() { + @BinaryField(index=1, length=32) + public int i1 = 1; + @BinaryField(index=2, length=32) + public int i2 = 2; + }; + + byte[] data = serialize(struct); + assertArrayEquals(new byte[]{0,0,0,1, 0,0,0,2}, data); + } +/* + @Test + public void basicBooleanTest() throws IOException { + BinaryStruct struct = new BinaryStruct() { + @BinaryField(index=1, length=1) + public boolean b1 = true; + @BinaryField(index=2, length=1) + public boolean b2 = false; + }; + + byte[] data = serialize(struct); + assertArrayEquals(new byte[]{(byte)0b1000_0000}, data); + } + + @Test + public void basicStringTest(){ + BinaryTestStruct struct = new BinaryTestStruct() { + @BinaryField(index=1, length=8*12) + public String s1; + + public void assertObj(Object... expected){ + assertEquals(s1, "hello world!"); + } + }; + + BinaryStructParser.parse(struct, "hello world!".getBytes()); + struct.assertObj(); + } + */ + + private byte[] serialize(BinaryStruct struct) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + BinaryStructOutputStream out = new BinaryStructOutputStream(buffer); + out.write(struct); + return buffer.toByteArray(); + } +} diff --git a/test/zutil/parser/json/JSONParserTest.java b/test/zutil/parser/json/JSONParserTest.java new file mode 100755 index 00000000..eb357322 --- /dev/null +++ b/test/zutil/parser/json/JSONParserTest.java @@ -0,0 +1,183 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.json; + +import org.junit.Test; +import zutil.parser.DataNode; +import zutil.parser.DataNode.DataType; +import zutil.parser.json.JSONParser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + + +public class JSONParserTest { + + @Test + public void nullString(){ + DataNode data = JSONParser.read(null); + assertNull(data); + } + + @Test + public void emptyString(){ + DataNode data = JSONParser.read(""); + assertNull(data); + } + + @Test + public void emptyMap(){ + DataNode data = JSONParser.read("{}"); + assertEquals(DataType.Map, data.getType()); + assertEquals( 0, data.size()); + } + + @Test + public void emptyList(){ + DataNode data = JSONParser.read("[]"); + assertEquals(DataType.List, data.getType()); + assertEquals( 0, data.size()); + } + + @Test + public void valueInt(){ + DataNode data = JSONParser.read("1234"); + assert(data.isValue()); + assertEquals( DataType.Number, data.getType()); + assertEquals( 1234, data.getInt()); + } + + @Test + public void valueDouble(){ + DataNode data = JSONParser.read("12.34"); + assert(data.isValue()); + assertEquals( DataType.Number, data.getType()); + assertEquals( 12.34, data.getDouble(), 0); + } + + @Test + public void valueBoolean(){ + DataNode data = JSONParser.read("false"); + assert(data.isValue()); + assertEquals( DataType.Boolean, data.getType()); + assertEquals( false, data.getBoolean()); + } + + @Test + public void valueBooleanUpperCase(){ + DataNode data = JSONParser.read("TRUE"); + assert(data.isValue()); + assertEquals( DataType.Boolean, data.getType()); + assertEquals( true, data.getBoolean()); + } + + @Test + public void valueStringNoQuotes(){ + DataNode data = JSONParser.read("teststring"); + assert(data.isValue()); + assertEquals( DataType.String, data.getType()); + assertEquals( "teststring", data.getString()); + } + + @Test + public void toManyCommasInList(){ + DataNode data = JSONParser.read("[1,2,3,]"); + assertEquals(DataType.List, data.getType()); + assertEquals( 1, data.get(0).getInt()); + assertEquals( 2, data.get(1).getInt()); + assertEquals( 3, data.get(2).getInt()); + } + + @Test + public void toManyCommasInMap(){ + DataNode data = JSONParser.read("{1:1,2:2,3:3,}"); + assertEquals(DataType.Map, data.getType()); + assertEquals( 1, data.get("1").getInt()); + assertEquals( 2, data.get("2").getInt()); + assertEquals( 3, data.get("3").getInt()); + } + + @Test + public void nullValueInList(){ + DataNode data = JSONParser.read("[1,null,3,]"); + assertEquals(DataType.List, data.getType()); + assertEquals(3, data.size()); + assertEquals( "1", data.get(0).getString()); + assertNull(data.get(1)); + assertEquals( "3", data.get(2).getString()); + } + + @Test + public void nullValueInMap(){ + DataNode data = JSONParser.read("{1:1,2:null,3:3,}"); + assertEquals(DataType.Map, data.getType()); + assertEquals(3, data.size()); + assertEquals( "1", data.getString("1")); + assertNull(data.get("2")); + assertEquals( "3", data.getString("3")); + } + + @Test + public void emptyStringInMap(){ + DataNode data = JSONParser.read("{1:{2:\"\"}}"); + assertEquals(DataType.Map, data.getType()); + assertEquals(1, data.size()); + assertEquals( "", data.get("1").getString("2")); + } + + + @Test + public void complexMap() { + String json = "{" + + "\"test1\": 1234," + + "\"TEST1\": 5678," + + "\"test3\": 1234.99," + + "\"test4\": \"91011\"," + + "\"test5\": [12,13,14,15]," + + "\"test6\": [\"a\",\"b\",\"c\",\"d\"]" + + "}"; + + DataNode data = JSONParser.read(json); + assert( data.isMap() ); + assert( 1234 == data.get("test1").getInt() ); + assert( 5678 == data.get("TEST1").getInt() ); + assert( 1234.99 == data.get("test3").getDouble() ); + assertEquals( "91011", data.get("test4").getString() ); + + assert( data.get("test5").isList() ); + assertEquals( 4, data.get("test5").size() ); + assertEquals( 12, data.get("test5").get(0).getInt() ); + assertEquals( 13, data.get("test5").get(1).getInt() ); + assertEquals( 14, data.get("test5").get(2).getInt() ); + assertEquals( 15, data.get("test5").get(3).getInt() ); + + assert( data.get("test6").isList() ); + assertEquals( 4, data.get("test6").size() ); + assertEquals( "a", data.get("test6").get(0).getString() ); + assertEquals( "b", data.get("test6").get(1).getString() ); + assertEquals( "c", data.get("test6").get(2).getString() ); + assertEquals( "d", data.get("test6").get(3).getString() ); + } +} diff --git a/test/zutil/parser/json/JSONSerializerBenchmark.java b/test/zutil/parser/json/JSONSerializerBenchmark.java new file mode 100755 index 00000000..42810c7c --- /dev/null +++ b/test/zutil/parser/json/JSONSerializerBenchmark.java @@ -0,0 +1,126 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.parser.json; + +import com.carrotsearch.junitbenchmarks.BenchmarkRule; +import org.junit.Rule; +import org.junit.Test; +import zutil.parser.json.JSONSerializerTest.TestClass; + +import java.io.*; + +import static org.junit.Assert.assertEquals; + + +public class JSONSerializerBenchmark { + private static final int TEST_EXECUTIONS = 2000; + + @Rule + public BenchmarkRule benchmarkRun = new BenchmarkRule(); + + @Test + public void testJavaLegacySerialize() throws InterruptedException, IOException, ClassNotFoundException{ + for(int i=0; i T sendReceiveObject(T sourceObj) throws IOException{ + return readObjectFromJson( + writeObjectToJson(sourceObj)); + } + + @SuppressWarnings("unchecked") + public static T readObjectFromJson(String json) throws IOException{ + StringReader bin = new StringReader(json); + JSONObjectInputStream in = new JSONObjectInputStream(bin); + T targetObj = (T) in.readObject(); + in.close(); + + return targetObj; + } + + public static String writeObjectToJson(T sourceObj) throws IOException{ + return writeObjectToJson(sourceObj, true); + } + public static String writeObjectToJson(T sourceObj, boolean metadata) throws IOException{ + StringOutputStream bout = new StringOutputStream(); + JSONObjectOutputStream out = new JSONObjectOutputStream(bout); + out.enableMetaData(metadata); + + out.writeObject(sourceObj); + out.flush(); + out.close(); + + String data = bout.toString(); + System.out.println(data); + + return data; + } + + /******************** Test Classes ************************************/ + + public static class TestClass implements Serializable{ + private static final long serialVersionUID = 1L; + String str; + double decimal; + TestObj obj1; + TestObj obj2; + + public TestClass init(){ + this.str = "abcd"; + this.decimal = 1.1; + this.obj1 = new TestObj().init(); + this.obj2 = new TestObj().init(); + return this; + } + + public static void assertEquals(TestClass obj1, TestClass obj2){ + Assert.assertEquals(obj1.str, obj2.str); + Assert.assertEquals(obj1.decimal, obj2.decimal, 0.001); + Assert.assertEquals(obj1.obj1, obj2.obj1); + Assert.assertEquals(obj1.obj2, obj2.obj2); + } + } + + public static class TestClassObjClone{ + TestObj obj1; + TestObj obj2; + + public TestClassObjClone init(){ + this.obj1 = this.obj2 = new TestObj().init(); + return this; + } + + public boolean equals(Object obj){ + return obj instanceof TestClassObjClone && + this.obj1.equals(((TestClassObjClone)obj).obj1) && + this.obj1 == this.obj2 && + ((TestClassObjClone)obj).obj1 == ((TestClassObjClone)obj).obj2; + } + } + + public static class TestObj implements Serializable{ + private static final long serialVersionUID = 1L; + int value; + + public TestObj init(){ + this.value = 42; + return this; + } + + public boolean equals(Object obj){ + return obj instanceof TestObj && + this.value == ((TestObj)obj).value; + } + } + + public static class TestClassArray{ + private int[] array; + + public TestClassArray init(){ + array = new int[]{1,2,3,4}; + return this; + } + + public boolean equals(Object obj){ + return obj instanceof TestClassArray && + Arrays.equals(this.array ,((TestClassArray)obj).array); + } + } + + public static class TestClassStringArray{ + private String[] array; + + public TestClassStringArray init(){ + array = new String[]{"test","string","array"}; + return this; + } + + public boolean equals(Object obj){ + return obj instanceof TestClassStringArray && + Arrays.equals(this.array ,((TestClassStringArray)obj).array); + } + } + + public static class TestClassMap{ + private HashMap map; + + public TestClassMap init(){ + map = new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", "value2"); + return this; + } + + public static void assertEquals(TestClassMap obj1, TestClassMap obj2){ + Assert.assertEquals(obj1.map, obj2.map); + } + } + + public static class TestClassList{ + private ArrayList list; + + public TestClassList init(){ + list = new ArrayList<>(); + list.add("value1"); + list.add("value2"); + return this; + } + + public static void assertEquals(TestClassList obj1, TestClassList obj2){ + Assert.assertEquals(obj1.list, obj2.list); + } + } +} diff --git a/test/zutil/struct/BloomFilterTest.java b/test/zutil/struct/BloomFilterTest.java new file mode 100755 index 00000000..2dfa9fbe --- /dev/null +++ b/test/zutil/struct/BloomFilterTest.java @@ -0,0 +1,87 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.struct; + +import junit.framework.TestCase; + +import java.text.DecimalFormat; +import java.util.HashSet; +import java.util.Random; + + +/** + * This code may be used, modified, and redistributed provided that the + * author tag below remains intact. + * + * @author Ian Clarke + */ + +public class BloomFilterTest extends TestCase { + public void testBloomFilter() { + DecimalFormat df = new DecimalFormat("0.00000"); + Random r = new Random(124445l); + int bfSize = 400000; + System.out.println("Testing " + bfSize + " bit SimpleBloomFilter"); + for (int i = 5; i < 10; i++) { + int addCount = 10000 * (i + 1); + BloomFilter bf = new BloomFilter(bfSize, addCount); + HashSet added = new HashSet(); + for (int x = 0; x < addCount; x++) { + int num = r.nextInt(); + added.add(num); + } + bf.addAll(added); + assertTrue("Assert that there are no false negatives", bf + .containsAll(added)); + + int falsePositives = 0; + for (int x = 0; x < addCount; x++) { + int num = r.nextInt(); + + // Ensure that this random number hasn't been added already + if (added.contains(num)) { + continue; + } + + // If necessary, record a false positive + if (bf.contains(num)) { + falsePositives++; + } + } + double expectedFP = bf.falsePosetiveProbability(); + double actualFP = (double) falsePositives / (double) addCount; + System.out.println("Got " + falsePositives + + " false positives out of " + addCount + " added items, rate = " + + df.format(actualFP) + ", expected = " + + df.format(expectedFP)); + double ratio = actualFP/expectedFP; + assertTrue( + "Assert that the actual false positive rate doesn't deviate by more than 10% from what was predicted, ratio: "+ratio, + ratio < 1.1); + } + } + + +} diff --git a/test/zutil/struct/CircularBufferTest.java b/test/zutil/struct/CircularBufferTest.java new file mode 100755 index 00000000..d32ff14f --- /dev/null +++ b/test/zutil/struct/CircularBufferTest.java @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.struct; + +import org.junit.Test; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + + +/** + * Created by Ziver on 2015-09-22. + */ +public class CircularBufferTest { + + @Test + public void addToEmpty() { + CircularBuffer buff = new CircularBuffer(0); + try { + buff.add(10); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) {} + } + + @Test + public void addOneElement() { + CircularBuffer buff = new CircularBuffer(1); + assertEquals(0, buff.size()); + buff.add(10); + assertEquals(1, buff.size()); + assertEquals((Integer) 10, buff.get(0)); + } + + @Test + public void addThreeElements() { + CircularBuffer buff = new CircularBuffer(10); + buff.add(10); + buff.add(11); + buff.add(12); + assertEquals(3, buff.size()); + assertEquals((Integer) 12, buff.get(0)); + assertEquals((Integer) 11, buff.get(1)); + assertEquals((Integer) 10, buff.get(2)); + } + + @Test + public void addOutOfRange() { + CircularBuffer buff = new CircularBuffer(2); + buff.add(10); + buff.add(11); + buff.add(12); + assertEquals(2, buff.size()); + assertEquals((Integer) 12, buff.get(0)); + assertEquals((Integer) 11, buff.get(1)); + try { + buff.get(2); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) {} + } + + @Test + public void iteratorEmpty() { + CircularBuffer buff = new CircularBuffer(10); + Iterator it = buff.iterator(); + + assert (!it.hasNext()); + try { + it.next(); + fail("NoSuchElementException was not thrown"); + } catch (NoSuchElementException e) {} + } + + @Test + public void iteratorThreeElements() { + CircularBuffer buff = new CircularBuffer(10); + buff.add(10); + buff.add(11); + buff.add(12); + + Iterator it = buff.iterator(); + assert (it.hasNext()); + assertEquals((Integer) 12, it.next()); + assert (it.hasNext()); + assertEquals((Integer) 11, it.next()); + assert (it.hasNext()); + assertEquals((Integer) 10, it.next()); + assert (!it.hasNext()); + + try { + it.next(); + fail("NoSuchElementException was not thrown"); + } catch (NoSuchElementException e) {} + } +} diff --git a/hal-core/src/se/hal/struct/devicedata/CurrentSensorData.java b/test/zutil/struct/TimedHashSetTest.java old mode 100644 new mode 100755 similarity index 55% rename from hal-core/src/se/hal/struct/devicedata/CurrentSensorData.java rename to test/zutil/struct/TimedHashSetTest.java index ae67a0f2..d92daf95 --- a/hal-core/src/se/hal/struct/devicedata/CurrentSensorData.java +++ b/test/zutil/struct/TimedHashSetTest.java @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Ziver Koc + * Copyright (c) 2015 Ziver Koc * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,44 +22,42 @@ * THE SOFTWARE. */ -package se.hal.struct.devicedata; +package zutil.struct; -import se.hal.intf.HalSensorData; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; -public class CurrentSensorData extends HalSensorData { +/** + * Created by Ziver on 2015-11-20. + */ +public class TimedHashSetTest { + public static final String ENTRY = "key"; - private double current; - - - public CurrentSensorData() { } - public CurrentSensorData(double current, long timestamp) { - this.current = current; - super.setTimestamp(timestamp); + @Test + public void zeroTTL() throws InterruptedException { + TimedHashSet set = new TimedHashSet(0); + set.add(ENTRY); + Thread.sleep(1); + assertFalse(set.contains(ENTRY)); } - - @Override - public String toString(){ - if (current < 0.1) - return current * 100 + " mA"; - return current + " A"; + @Test + public void tenMsTTL() throws InterruptedException { + TimedHashSet set = new TimedHashSet(10); + set.add(ENTRY); + Thread.sleep(1); + assert(set.contains(ENTRY)); + Thread.sleep(10); + assertFalse(set.contains(ENTRY)); } - // ---------------------------------------- - // Storage methods - // ---------------------------------------- - - /** - * @return number representing Volts measured - */ - @Override - public double getData() { - return current; + @Test + public void oneSecTTL() throws InterruptedException { + TimedHashSet set = new TimedHashSet(1000); + set.add(ENTRY); + Thread.sleep(1); + assert(set.contains(ENTRY)); } - - @Override - public void setData(double current){ - this.current = current; - } -} +} \ No newline at end of file diff --git a/test/zutil/ui/ConsoleTest.java b/test/zutil/ui/ConsoleTest.java new file mode 100755 index 00000000..bb78b1f3 --- /dev/null +++ b/test/zutil/ui/ConsoleTest.java @@ -0,0 +1,49 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * 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. + */ + +package zutil.ui; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + + +public class ConsoleTest { + public static void main(String[] args) throws IOException{ + Console terminal = new Console("Console Test"); + terminal.enableTray(true); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + while(true){ + System.out.println("hello= "+in.readLine()); + for(int i=0; i<2 ;i++){ + System.out.println(i+"Hello World!!!sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"); + System.err.println(i+"Hello World!!!sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"); + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + } + } + } +}