'
+
+ +'
'+hlselectorInput+' Input of Low Selector '
+ if(hlselectorInput != -1){
+
+
+ for (var i = 1; i <= hlselectorInput ; i++ ) {
+ if(i == 1){
+
+ LS4Input_characterisation += '
'
+ }else{
+
+ LS4Input_characterisation += '
'
+ if(i == 2){
+ LS4Input_characterisation +='' + '
'
+ + '
'
+
+ + 'Next '
+ + '
'
+
+
+ $(mainDiv).html(LS4Input_characterisation);
+
+ var w = 900;
+ var h = 500;
+
+var width = $(window).width();
+
+ if ($(window).width() < 500) {
+ width = $(this).width();
+ paper = new Raphael(document.getElementById('canvas1'), '100%', 500);
+ paper.setViewBox(0,0,w,h,true);
+ paper.setSize('100%', 500);
+ }else
+ {
+ paper = new Raphael(document.getElementById('canvas1'), '100%', 600);
+ paper.setViewBox(0,0,w,h,true);
+ paper.setSize('100%', 600);
+ }
+
+for (var i = 1; i <= hlselectorInput ; i++ ) {
+
+ if(hlselectorInput == 4 )
+ {
+ $('#LS4Input_Slider_'+i+'').css({'width':'48%','margin':'5px 1%','float':'left'});
+ $('#nxttype').css('margin','10px 2%');
+ }
+
+
+ }
+// value for slider 1
+ var slider_1 = document.getElementById("Input_1");
+ var output_1 = document.getElementById("demo_1");
+ output_1.innerHTML = slider_1.value;
+
+ slider_1.oninput = function() {
+ output_1.innerHTML = this.value;
+ checkOutput();
+ $('#nxttype').prop('hidden', false);
+ }
+
+// value for slider 2
+ var slider_2 = document.getElementById("Input_2");
+ var output_2 = document.getElementById("demo_2");
+ output_2.innerHTML = slider_2.value;
+
+ slider_2.oninput = function() {
+ output_2.innerHTML = this.value;
+ checkOutput();
+ $('#nxttype').prop('hidden', false);
+ }
+
+// value for slider 3
+ var slider_3 = document.getElementById("Input_3");
+ var output_3 = document.getElementById("demo_3");
+ output_3.innerHTML = slider_3.value;
+
+ slider_3.oninput = function() {
+ output_3.innerHTML = this.value;
+ checkOutput();
+ $('#nxttype').prop('hidden', false);
+ }
+
+// value for slider 4
+ var slider_4 = document.getElementById("Input_4");
+ var output_4 = document.getElementById("demo_4");
+ output_4.innerHTML = slider_4.value;
+
+ slider_4.oninput = function() {
+ output_4.innerHTML = this.value;
+ checkOutput();
+ $('#nxttype').prop('hidden', false);
+ }
+
+
+ function checkOutput(){
+
+ inputValA = slider_1.value;
+ inputValB = slider_2.value;
+ inputValC = slider_3.value;
+ inputValD = slider_4.value;
+
+ paper.clear();
+ LS4inputDiagram();
+
+ InputLabel(160, 150, inputValA, 'blue');
+ InputLabel(300, 340, inputValB, 'blue');
+ InputLabel(300, 85, inputValC, 'blue');
+ InputLabel(160, 270, inputValD, 'blue');
+
+ min = Math.min(inputValA, inputValB, inputValC, inputValD);
+ InputLabel(440, 210, min, 'red');
+ }
+
+
+
+
+
+
+
+
+
+ // next type click
+ $('#nxttype').on(
+ 'click', function() {
+
+
+
+ LSInput_optionFlag++;
+
+ LS4Input_CharacterisationData.hlselectorType = hlselectorType;
+ LS4Input_CharacterisationData.hlselectorInput = hlselectorInput;
+ LS4Input_CharacterisationData.inputValA = inputValA;
+ LS4Input_CharacterisationData.inputValB = inputValB;
+ LS4Input_CharacterisationData.inputValC = inputValC;
+ LS4Input_CharacterisationData.output = min;
+// console.log(LS4Input_CharacterisationData);
+ ExpTrackData.ls4inputCharactData = LS4Input_CharacterisationData;
+// console.log(ExpTrackData);
+
+
+ if(LSInput_optionFlag != 0 && HSInput_optionFlag != 0 && RLInput_optionFlag != 0 && HLInput_optionFlag != 0 && LLInput_optionFlag != 0){
+
+// alert("to the next level");
+ SelectAppToConfigure();
+
+ }else{
+
+ H2L_Configure();
+ }
+
+
+
+ });
+
+
+
+
+
+// called draw function of low selector with 4 input
+
+ LS4inputDiagram();
+
+
+
+}
+
+});
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/experiment/simulation/js/H2L_characterisation/RLInput_Characterisation.js b/experiment/simulation/js/H2L_characterisation/RLInput_Characterisation.js
new file mode 100644
index 0000000..6b8e666
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/RLInput_Characterisation.js
@@ -0,0 +1,169 @@
+//var SINGLEACTINGCYLINDER = SINGLEACTINGCYLINDER || {};
+
+$(function () {
+
+//SINGLEACTINGCYLINDER.Characterisation_RLInput = function(hlselectorType, limitValue) {
+
+ Characterisation_RLInput = function(hlselectorType, limitValue){
+
+ var RLInput_arr = [];
+
+ $("#mainDiv").html('');
+
+ var RLInput_characterisation = '';
+ RLInput_characterisation +='
'
+
+ + '
'
+ + '
'
+
+ + 'Next '
+ + '
'
+
+
+ $(mainDiv).html(RLInput_characterisation);
+
+ var w = 900;
+ var h = 500;
+
+var width = $(window).width();
+
+ if ($(window).width() < 500) {
+ width = $(this).width();
+ paper = new Raphael(document.getElementById('canvas1'), '100%', 500);
+ paper.setViewBox(0,0,w,h,true);
+ paper.setSize('100%', 500);
+ }else
+ {
+ paper = new Raphael(document.getElementById('canvas1'), '100%', 600);
+ paper.setViewBox(0,0,w,h,true);
+ paper.setSize('100%', 600);
+ }
+
+ $('#RLInput_Slider_1').css({'width':'70%','margin':'5px 15%'});
+ $('#nxttype').css('margin','10px 9%');
+// value for slider 1
+ var slider_1 = document.getElementById("Input_1");
+ var output_1 = document.getElementById("demo_1");
+ output_1.innerHTML = slider_1.value;
+
+ slider_1.oninput = function() {
+ output_1.innerHTML = this.value;
+ checkOutput();
+ $('#nxttype').prop('hidden', false);
+
+
+
+ }
+
+
+
+ function checkOutput(){
+
+ inputValA = slider_1.value;
+
+ paper.clear();
+ RLinputDiagram(limitValue);
+
+ InputLabel(160, 210, inputValA, 'blue');
+// InputLabel(300, 310, limitValue, 'blue');
+ if(inputValA >= limitValue){
+ outputval = limitValue;
+ InputLabel(440, 210, outputval, 'red');
+
+ }else{
+ outputval = inputValA;
+ InputLabel(440, 210, outputval, 'red');
+ }
+
+
+ }
+
+
+
+
+
+
+
+
+
+ // next type click
+ $('#nxttype').on(
+ 'click', function() {
+
+
+
+ RLInput_optionFlag++;
+
+ RLInput_CharacterisationData.hlselectorType = hlselectorType;
+ RLInput_CharacterisationData.limitValue = limitValue;
+ RLInput_CharacterisationData.inputValA = inputValA;
+ RLInput_CharacterisationData.output = outputval;
+// console.log(RLInput_CharacterisationData);
+ ExpTrackData.rlinputCharactData = RLInput_CharacterisationData;
+// console.log(ExpTrackData);
+
+
+ if(LSInput_optionFlag != 0 && HSInput_optionFlag != 0 && RLInput_optionFlag != 0 && HLInput_optionFlag != 0 && LLInput_optionFlag != 0){
+
+// alert("to the next level");
+ SelectAppToConfigure();
+
+ }else{
+
+ H2L_Configure();
+ }
+
+
+
+ });
+
+
+
+
+
+// called draw function of rate limiter
+
+ RLinputDiagram(limitValue);
+
+
+
+}
+
+});
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/HLInputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HLInputDiagram.js
new file mode 100644
index 0000000..59ecb2a
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HLInputDiagram.js
@@ -0,0 +1,87 @@
+
+function HLinputDiagram(limitValue){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+ InputLabel(300, 310, limitValue, 'blue');
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-150), "High limit Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+290)+","+ (y-53)+" l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+ paper.path("M "+(x+295)+","+ (y-55)+" l 0 20").
+ attr({"stroke-width" : 2
+ });
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ paper.path("M "+(x+140)+","+ (y+10)+"l 60 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+150), (y+25), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // X input
+
+ paper.text((x+250), (y+75), "X").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+}
+
+function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+ };
+// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS2InputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS2InputDiagram.js
new file mode 100644
index 0000000..56ad0c8
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS2InputDiagram.js
@@ -0,0 +1,86 @@
+
+function HS2inputDiagram(){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-150), "High Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+290)+","+ (y-53)+" l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ paper.path("M "+(x+140)+","+ (y+10)+"l 60 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+150), (y+25), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ paper.path("M "+(x+250)+","+ (y+120)+" l 0 -60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y+115), "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+}
+
+
+ function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+ };
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS3InputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS3InputDiagram.js
new file mode 100644
index 0000000..ca507fc
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS3InputDiagram.js
@@ -0,0 +1,99 @@
+
+function HS3inputDiagram(){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-170), "3 Input High Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+290)+","+ (y-53)+" l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ paper.path("M "+(x+140)+","+ (y+10)+"l 60 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+150), (y+25), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ paper.path("M "+(x+250)+","+ (y+120)+" l 0 -60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y+115), "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ // c input
+ paper.path("M "+(x+250)+","+ (y-100)+" l 0 60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y-90), "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+}
+
+function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ };
+// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS4InputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS4InputDiagram.js
new file mode 100644
index 0000000..57b3248
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/HS4InputDiagram.js
@@ -0,0 +1,111 @@
+// JavaScript Document
+function HS4inputDiagram(){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-180), "4 Input High Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+290)+","+ (y-53)+" l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+
+ paper.path("M "+(x+150)+","+ (y-45)+"l 60 25").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+160), (y-55), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ // b input
+ paper.path("M "+(x+250)+","+ (y+120)+" l 0 -60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y+115), "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ // c input
+ paper.path("M "+(x+250)+","+ (y-100)+" l 0 60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y-90), "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ // d input
+ paper.path("M "+(x+150)+","+ (y+60)+"l 60 -25").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+160), (y+70), "d").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+}
+
+function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+ };
+// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/LLInputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LLInputDiagram.js
new file mode 100644
index 0000000..5a17b34
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LLInputDiagram.js
@@ -0,0 +1,87 @@
+
+function LLinputDiagram(limitValue){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+ InputLabel(300, 310, limitValue, 'blue');
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-150), "Low limit Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+300)+","+ (y-53)+" l -12 8 l 12 8").
+ attr({"stroke-width" : 2
+ });
+
+ paper.path("M "+(x+295)+","+ (y-55)+" l 0 20").
+ attr({"stroke-width" : 2
+ });
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ paper.path("M "+(x+140)+","+ (y+10)+"l 60 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+150), (y+25), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // X input
+
+ paper.text((x+250), (y+75), "X").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+}
+
+function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+ };
+// JavaScript Document// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS2InputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS2InputDiagram.js
new file mode 100644
index 0000000..c7c0b0c
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS2InputDiagram.js
@@ -0,0 +1,87 @@
+
+function LS2inputDiagram(){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-150), "2 Input Low Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+300)+","+ (y-53)+" l -12 8 12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ paper.path("M "+(x+140)+","+ (y+10)+"l 60 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+150), (y+25), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ paper.path("M "+(x+250)+","+ (y+120)+" l 0 -60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y+115), "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+}
+
+function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+ };
+// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS3InputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS3InputDiagram.js
new file mode 100644
index 0000000..05baf1d
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS3InputDiagram.js
@@ -0,0 +1,98 @@
+
+function LS3inputDiagram(){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-150), "3 Input Low Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+300)+","+ (y-53)+" l -12 8 l 12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ paper.path("M "+(x+140)+","+ (y+10)+"l 60 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+150), (y+25), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ paper.path("M "+(x+250)+","+ (y+120)+" l 0 -60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y+115), "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ // c input
+ paper.path("M "+(x+250)+","+ (y-100)+" l 0 60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y-90), "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+}
+
+function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+ };
+// JavaScript Document// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS4InputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS4InputDiagram.js
new file mode 100644
index 0000000..d529fc6
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/LS4InputDiagram.js
@@ -0,0 +1,111 @@
+// JavaScript Document// JavaScript Document
+function LS4inputDiagram(){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-150), "4 Input Low Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+300)+","+ (y-53)+" l -12 8 l 12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+
+ // a input
+ paper.path("M "+(x+150)+","+ (y-45)+"l 60 25").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+160), (y-55), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ // b input
+ paper.path("M "+(x+250)+","+ (y+120)+" l 0 -60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y+115), "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ // c input
+ paper.path("M "+(x+250)+","+ (y-100)+" l 0 60").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+265), (y-90), "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // d input
+ paper.path("M "+(x+150)+","+ (y+60)+"l 60 -25").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+160), (y+70), "d").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+}
+
+function InputLabel(x, y, text,clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+ };
+// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_characterisation/animationDiagrams/RLInputDiagram.js b/experiment/simulation/js/H2L_characterisation/animationDiagrams/RLInputDiagram.js
new file mode 100644
index 0000000..3093243
--- /dev/null
+++ b/experiment/simulation/js/H2L_characterisation/animationDiagrams/RLInputDiagram.js
@@ -0,0 +1,87 @@
+
+function RLinputDiagram(limitValue){
+// paper = new Raphael(document.getElementById('canvas'), '100%', 700);
+
+
+
+ x = 50;
+ y = 200;
+
+ InputLabel(300, 310, limitValue, 'blue');
+
+// InputLabel((x+110), (y+10), 34);
+
+// InputLabel(300, 340, 34);
+
+ paper.text((x+250), (y-150), "Rate limiter Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 30,
+ "font-family": "sans-serif"
+ });
+
+ paper.circle((x+250), (y+10), 50).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ paper.rect((x+280), (y-60), 35, 30).
+ attr({"stroke-width" : 1
+ });
+
+
+ paper.path("M "+(x+285)+","+ (y-53)+" l 12 15 12 -15 ").
+ attr({"stroke-width" : 2
+ });
+
+ paper.path("M "+(x+285)+","+ (y-46)+" l 25 0").
+ attr({"stroke-width" : 2
+ });
+
+ // out
+ paper.path("M "+(x+300)+","+ (y+10)+" l 60 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+320), (y+25), "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ paper.path("M "+(x+140)+","+ (y+10)+"l 60 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ paper.text((x+150), (y+25), "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // X input
+
+ paper.text((x+250), (y+75), "X").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+}
+
+function InputLabel(x, y, text, clr){
+
+ paper.text(x, y, text+"%").attr({
+ stroke : clr,
+ 'font-size' : 25,
+ "font-family": "sans-serif"
+ });
+
+
+
+ };
+// JavaScript Document// JavaScript Document// JavaScript Document
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_config/H2L_Configuration.js b/experiment/simulation/js/H2L_config/H2L_Configuration.js
new file mode 100644
index 0000000..c3ca8a0
--- /dev/null
+++ b/experiment/simulation/js/H2L_config/H2L_Configuration.js
@@ -0,0 +1,343 @@
+
+
+H2L_Configure = function(){
+
+
+
+
+ $("#mainDiv").html('');
+
+ var configure = '';
+ configure +='
'
+ +'
'
+ +'
'
+ +'
High Low Selector Configuration '
+ +'
'
+ +'
'
+ +'Select Type: '
+ +'
'
+ +'
'
+ +''
+ +'Select '
+ if(HSInput_optionFlag != 0){
+
+ configure +='High Selector '
+ }else{
+
+ configure +='High Selector '
+ }
+ if(LSInput_optionFlag != 0){
+
+ configure +='Low Selector '
+ }else{
+
+ configure +='Low Selector '
+ }
+ if(RLInput_optionFlag != 0){
+
+ configure +='Rate Limiter '
+ }else{
+
+ configure +='Rate Limiter '
+ }
+ if(HLInput_optionFlag != 0){
+
+ configure +='High Limit '
+ }else{
+
+ configure +='High Limit '
+ }
+ if(LLInput_optionFlag != 0){
+
+ configure +='Low Limit '
+ }else{
+
+ configure +='Low Limit '
+ }
+ configure +=' '
+ +'
'
+ +'
'
+
+ +'
'
+
+ +'
'
+ +'
'
+ +'Set Limit Value (in %): '
+ +'
'
+ +'
'
+ +''
+ +'Select '
+ for(var i = 1 ; i<=99; i++)
+ {
+
+
+ configure +=''+i+' '
+
+ }
+ configure +=' '
+ //+' %'
+ +'
'
+// +'
(Set limit value between 1 to 99 )
'
+// +'
'
+ +'
'
+
+
+
+
+ +'
'
+ +'
'
+ +'Power Supply : '
+ +'
'
+ +'
'
+ +'24 VDC'
+ +'
'
+
+ +'
'
+ +'
'
+ +'Output : '
+ +'
'
+ +'
'
+ +''
+ +'Select '
+ if(HSInput_optionFlag != 0){
+
+ configure +='Highest amongst all '
+ }else{
+
+ configure +='Highest amongst all '
+ }
+ if(LSInput_optionFlag != 0){
+
+ configure +='Lowest amongst all '
+ }else{
+
+ configure +='Lowest amongst all '
+ }
+ if(RLInput_optionFlag != 0){
+ configure +='Varying signal '
+ }else{
+ configure +='Varying signal '
+ }
+ if(HLInput_optionFlag != 0){
+ configure +=+'Threshold value set is high '
+ }else{
+ configure +='Threshold value set is high '
+ }
+ if(LLInput_optionFlag != 0){
+ configure +='Threshold value set is low '
+ }else{
+ configure +='Threshold value set is low '
+ }
+
+ configure +=' '
+ +'
'
+ +'
'
+
+
+ +'
'
+ +'
'
+ +'Check Operation '
+ +'Next Level '
+ +'
'
+ +'
'
+ +'
'
+
+ +'
' // col close
+ +'
' // row close
+ +'
'; // container close
+
+
+ $("#mainDiv").html(configure);
+
+
+ $('select#hlSelectorType').on(
+ 'change',
+ function() {
+
+ if (this.value == "high" || this.value == "low") {
+
+ $("#limitValue").val("-1");
+ $('#div_limitValue').hide();
+ $('#div_hlSelectorInput').show();
+
+ } else if (this.value == "ratelimiter"
+ || this.value == "highlimit"
+ || this.value == "lowlimit") {
+
+ $( "#hlSelectorInput" ).val("-1");
+ $('#div_hlSelectorInput').hide();
+ $('#div_limitValue').show();
+
+ }
+ /*else if(this.value == "-1"){
+
+ $( "#hlSelectorInput" ).val("-1");
+ $('#div_hlSelectorInput').hide();
+ $("#limitValue").val("-1");
+ $('#div_limitValue').hide();
+ }*/
+
+ });
+
+
+
+
+ $('#H2L_checkConfig').on(
+ 'click', function() {
+
+ chkConfigCnt = 0;
+ var H2LInput_configData = {};
+
+ var hlselectorType = $( "#hlSelectorType option:selected" ).val();
+ var hlselectorInput = parseInt($( "#hlSelectorInput option:selected" ).val());
+ var limitValue = parseInt($("#limitValue option:selected").val());
+ var output = $( "#output option:selected" ).val();
+ var outputtxt = $( "#output option:selected" ).text();
+
+// console.log(hlselectorInput, limitValue);
+
+ if(hlselectorType != "-1"){
+
+ if(hlselectorType == "high" || hlselectorType == "low"){
+
+ if(hlselectorInput != "-1" && output != "-1"){
+
+ if(hlselectorType =="high" && output == "0"){
+
+
+ chkConfigCnt++;
+
+ }else if(hlselectorType =="low" && output == "1"){
+
+ chkConfigCnt++;
+
+ }else{
+
+ alertify.alert("Please select the correct output as per selected high low selector type");
+ }
+
+
+
+ }else{
+
+ alertify.alert("Please select all the fields");
+
+ }
+
+
+// H2LInput_configData.HLselectorType = hlselectorType;
+// H2LInput_configData.HLselectorInput = hlselectorInput;
+//// H2LInput_configData.LimitValue = limitValue;
+// H2LInput_configData.output = output;
+// ExpTrackData.h2linputConfigData = H2LInput_configData;
+// console.log(ExpTrackData);
+
+
+
+
+ }else{
+
+
+ if(limitValue != "-1" && output != "-1"){
+
+ if(hlselectorType =="ratelimiter" && output == "2"){
+
+ chkConfigCnt++;
+
+ }else if(hlselectorType =="highlimit" && output == "3"){
+
+ chkConfigCnt++;
+
+ }else if(hlselectorType =="lowlimit" && output == "4"){
+
+ chkConfigCnt++;
+
+ }else{
+
+ alertify.alert("Please select the correct output as per selected high low selector type");
+ }
+
+
+
+ }else{
+
+ alertify.alert("Please select all the fields");
+
+ }
+
+
+// H2LInput_configData.HLselectorType = hlselectorType;
+//// H2LInput_configData.HLselectorInput = hlselectorInput;
+// H2LInput_configData.LimitValue = limitValue;
+// H2LInput_configData.output = output;
+// ExpTrackData.h2linputConfigData = H2LInput_configData;
+// console.log(ExpTrackData);
+
+
+ }
+
+ }else{
+
+ alertify.alert("Please select high low selector type");
+ }
+
+
+
+ if(chkConfigCnt == "1"){
+
+
+
+ alertify.alert("Configuration is successful.
Please click next level to identify right symbol for high low selector from symbol liabrary");
+ $("#hlSelectorType, #hlselectorInput, #output, #limitValue").prop("disabled", true);
+ $('#H2L_wiringDiagram').show();
+
+ H2LInput_configData.HLselectorType = hlselectorType;
+ H2LInput_configData.HLselectorInput = hlselectorInput;
+ H2LInput_configData.LimitValue = limitValue;
+ H2LInput_configData.output = outputtxt;
+
+ ExpTrackData.h2linputConfigData = H2LInput_configData;
+// console.log(ExpTrackData);
+
+
+ }
+
+
+
+ });
+
+
+
+ $('#H2L_wiringDiagram').on(
+ 'click', function() {
+
+ var hlselectorType = $( "#hlSelectorType option:selected" ).val();
+ var hlselectorInput = parseInt($( "#hlSelectorInput option:selected" ).val());
+ var limitValue = parseInt($("#limitValue option:selected").val());
+
+
+
+ connectionLevel(hlselectorType, hlselectorInput, limitValue);
+
+
+ });
+}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_connections/CheckConnectionForH2L.js b/experiment/simulation/js/H2L_connections/CheckConnectionForH2L.js
new file mode 100644
index 0000000..db52b99
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/CheckConnectionForH2L.js
@@ -0,0 +1,106 @@
+
+checkConnectionsForH2L = function(hlselectorType, hlselectorInput, limitValue,
+ jsonarray) {
+
+ var temp = JSON.parse(jsonarray);
+
+ var connData = {};
+
+ if (temp.length != 0) {
+
+ if (temp.length == 1) {
+
+ // high selector connection check
+
+ // high selector with 2 inputs connection check
+ if (hlselectorType == "high" && hlselectorInput == "2") {
+
+ Identify_H2L_HS2Input(hlselectorType, hlselectorInput,
+ jsonarray);
+
+ }
+ // high selector with 3 inputs connection check
+ if (hlselectorType == "high" && hlselectorInput == "3") {
+
+ Identify_H2L_HS3Input(hlselectorType, hlselectorInput,
+ jsonarray);
+ }
+ // high selector with 4 inputs connection check
+ if (hlselectorType == "high" && hlselectorInput == "4") {
+
+ Identify_H2L_HS4Input(hlselectorType, hlselectorInput,
+ jsonarray);
+
+ }
+
+ // low selector connection check
+
+ // low selector with 2 inputs connection check
+ if (hlselectorType == "low" && hlselectorInput == "2") {
+
+ Identify_H2L_LS2Input(hlselectorType, hlselectorInput,
+ jsonarray);
+
+ }
+ // low selector with 3 inputs connection check
+ if (hlselectorType == "low" && hlselectorInput == "3") {
+
+ Identify_H2L_LS3Input(hlselectorType, hlselectorInput,
+ jsonarray);
+
+ }
+ // low selector with 4 inputs connection check
+ if (hlselectorType == "low" && hlselectorInput == "4") {
+
+ Identify_H2L_LS4Input(hlselectorType, hlselectorInput,
+ jsonarray);
+
+ }
+
+ // Limiter Selector Connection check
+
+ // Rate Limiter connection check
+ // rate limiter with 1 inputs connection check
+ if (hlselectorType == "ratelimiter") {
+
+ Identify_RateLimiter(hlselectorType, limitValue, jsonarray);
+
+ }
+
+ // High Limit connection check
+ // High Limit with 1 inputs connection check
+ if (hlselectorType == "highlimit") {
+
+ Identify_HighLimit(hlselectorType, limitValue, jsonarray);
+
+ }
+
+ // Low Limit connection check
+ // Low Limit with 1 inputs connection check
+ if (hlselectorType == "lowlimit") {
+
+ Identify_LowLimit(hlselectorType, limitValue, jsonarray);
+
+ }
+
+
+
+ connData.HLselectorType = hlselectorType;
+ connData.HLselectorInput = hlselectorInput;
+ connData.connDiagjson = jsonarray;
+ connData.chkConnCnt = ConnFlagCnt;
+ connData.chkRightConn = rightConn;
+ // console.log(connData);
+ ExpTrackData.connData = connData
+// console.log(ExpTrackData);
+ } else {
+
+ alertify.alert("Please select only one symbol at a time to identify");
+ }
+ } else {
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+}
diff --git a/experiment/simulation/js/H2L_connections/Connhint.js b/experiment/simulation/js/H2L_connections/Connhint.js
new file mode 100644
index 0000000..4b8227c
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/Connhint.js
@@ -0,0 +1,71 @@
+ConnHint = function(hlselectorType, hlselectorInput, limitValue) {
+
+ // console.log(appId,type) ;
+
+ // high selector connection hint
+
+ // high selector with 2 inputs connection hint
+ if (hlselectorType == "high" && hlselectorInput == "2") {
+
+ $("#HS_2Input").css("display", "block");
+
+ }
+ // high selector with 3 inputs connection hint
+ if (hlselectorType == "high" && hlselectorInput == "3") {
+
+ $("#HS_3Input").css("display", "block");
+ }
+ // high selector with 4 inputs connection hint
+ if (hlselectorType == "high" && hlselectorInput == "4") {
+
+ $("#HS_4Input").css("display", "block");
+
+ }
+
+ // low selector connection hint
+
+ // low selector with 2 inputs connection hint
+ if (hlselectorType == "low" && hlselectorInput == "2") {
+
+ $("#LS_2Input").css("display", "block");
+
+ }
+ // low selector with 3 inputs connection hint
+ if (hlselectorType == "low" && hlselectorInput == "3") {
+
+ $("#LS_3Input").css("display", "block");
+
+ }
+ // low selector with 4 inputs connection hint
+ if (hlselectorType == "low" && hlselectorInput == "4") {
+
+ $("#LS_4Input").css("display", "block");
+ }
+
+ // Limiter Selector Connection hint
+ // Rate Limiter connection hint
+
+ // rate limiter with 1 inputs connection hint
+ if (hlselectorType == "ratelimiter") {
+
+ $("#Limiter_RL").css("display", "block");
+
+ }
+
+ // High Limit connection hint
+ // High Limit with 1 inputs connection hint
+ if (hlselectorType == "highlimit") {
+
+ $("#Limiter_HL").css("display", "block");
+
+ }
+
+ // Low Limit connection check
+ // Low Limit with 1 inputs connection check
+ if (hlselectorType == "lowlimit") {
+
+ $("#Limiter_LL").css("display", "block");
+
+ }
+
+}
diff --git a/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith2Input.js b/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith2Input.js
new file mode 100644
index 0000000..5976f26
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith2Input.js
@@ -0,0 +1,137 @@
+
+
+Identify_H2L_HS2Input = function(hlselectorType, hlselectorInput, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ High_2Input_RightSelector = 0;
+
+ High_2Input_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "highselector_2input"){
+
+ High_2Input_RightSelector = 1;
+
+
+ } else{
+
+ High_2Input_WrongSelector = 1;
+ CheckWrongConnectionH2L_HS2Input();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_HS2Input();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_HS2Input = function(){
+
+ if(High_2Input_RightSelector == 1 && High_2Input_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(High_2Input_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_HS2Input = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(High_2Input_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith3Input.js b/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith3Input.js
new file mode 100644
index 0000000..0510626
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith3Input.js
@@ -0,0 +1,137 @@
+
+
+Identify_H2L_HS3Input = function(hlselectorType, hlselectorInput, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ High_3Input_RightSelector = 0;
+
+ High_3Input_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "highselector_3input"){
+
+ High_3Input_RightSelector = 1;
+
+
+ } else{
+
+ High_3Input_WrongSelector = 1;
+ CheckWrongConnectionH2L_HS3Input();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_HS3Input();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_HS3Input = function(){
+
+ if(High_3Input_RightSelector == 1 && High_3Input_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(High_3Input_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_HS3Input = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(High_3Input_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith4Input.js b/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith4Input.js
new file mode 100644
index 0000000..a6a1db2
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/High Selector/highSelectorWith4Input.js
@@ -0,0 +1,137 @@
+
+
+Identify_H2L_HS4Input = function(hlselectorType, hlselectorInput, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ High_4Input_RightSelector = 0;
+
+ High_4Input_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "highselector_4input"){
+
+ High_4Input_RightSelector = 1;
+
+
+ } else{
+
+ High_4Input_WrongSelector = 1;
+ CheckWrongConnectionH2L_HS4Input();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_HS4Input();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_HS4Input = function(){
+
+ if(High_4Input_RightSelector == 1 && High_4Input_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(High_4Input_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_HS4Input = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(High_4Input_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/Limiters/Limiter_HighLimit.js b/experiment/simulation/js/H2L_connections/Limiters/Limiter_HighLimit.js
new file mode 100644
index 0000000..090abcf
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/Limiters/Limiter_HighLimit.js
@@ -0,0 +1,137 @@
+
+
+Identify_HighLimit = function(hlselectorType, limitValue, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ HighLimit_RightSelector = 0;
+
+ HighLimit_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "selector_highlimit"){
+
+ HighLimit_RightSelector = 1;
+
+
+ } else{
+
+ HighLimit_WrongSelector = 1;
+ CheckWrongConnectionH2L_HighLimit();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_HighLimit();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_HighLimit = function(){
+
+ if(HighLimit_RightSelector == 1 && HighLimit_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(HighLimit_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_HighLimit = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(HighLimit_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/Limiters/Limiter_LowLimit.js b/experiment/simulation/js/H2L_connections/Limiters/Limiter_LowLimit.js
new file mode 100644
index 0000000..d332c9e
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/Limiters/Limiter_LowLimit.js
@@ -0,0 +1,137 @@
+
+
+Identify_LowLimit = function(hlselectorType, limitValue, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ LowLimit_RightSelector = 0;
+
+ LowLimit_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "selector_lowlimit"){
+
+ LowLimit_RightSelector = 1;
+
+
+ } else{
+
+ LowLimit_WrongSelector = 1;
+ CheckWrongConnectionH2L_LowLimit();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_LowLimit();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_LowLimit = function(){
+
+ if(LowLimit_RightSelector == 1 && LowLimit_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(LowLimit_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_LowLimit = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(LowLimit_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/Limiters/Limiter_Ratelimiter.js b/experiment/simulation/js/H2L_connections/Limiters/Limiter_Ratelimiter.js
new file mode 100644
index 0000000..d3cb212
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/Limiters/Limiter_Ratelimiter.js
@@ -0,0 +1,137 @@
+
+
+Identify_RateLimiter = function(hlselectorType, limitValue, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ RateLimiter_RightSelector = 0;
+
+ RateLimiter_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "selector_ratelimiter"){
+
+ RateLimiter_RightSelector = 1;
+
+
+ } else{
+
+ RateLimiter_WrongSelector = 1;
+ CheckWrongConnectionH2L_RateLimiter();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_RateLimiter();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_RateLimiter = function(){
+
+ if(RateLimiter_RightSelector == 1 && RateLimiter_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(RateLimiter_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_RateLimiter = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(RateLimiter_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith2Input.js b/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith2Input.js
new file mode 100644
index 0000000..4b520c8
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith2Input.js
@@ -0,0 +1,137 @@
+
+
+Identify_H2L_LS2Input = function(hlselectorType, hlselectorInput, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ Low_2Input_RightSelector = 0;
+
+ Low_2Input_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "lowselector_2input"){
+
+ Low_2Input_RightSelector = 1;
+
+
+ } else{
+
+ Low_2Input_WrongSelector = 1;
+ CheckWrongConnectionH2L_LS2Input();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_LS2Input();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_LS2Input = function(){
+
+ if(Low_2Input_RightSelector == 1 && Low_2Input_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(Low_2Input_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_LS2Input = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(Low_2Input_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith3Input.js b/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith3Input.js
new file mode 100644
index 0000000..5222e30
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith3Input.js
@@ -0,0 +1,137 @@
+
+
+Identify_H2L_LS3Input = function(hlselectorType, hlselectorInput, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ Low_3Input_RightSelector = 0;
+
+ Low_3Input_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "lowselector_3input"){
+
+ Low_3Input_RightSelector = 1;
+
+
+ } else{
+
+ Low_3Input_WrongSelector = 1;
+ CheckWrongConnectionH2L_LS3Input();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_LS3Input();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_LS3Input = function(){
+
+ if(Low_3Input_RightSelector == 1 && Low_3Input_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(Low_3Input_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_LS3Input = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(Low_3Input_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith4Input.js b/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith4Input.js
new file mode 100644
index 0000000..c0c146a
--- /dev/null
+++ b/experiment/simulation/js/H2L_connections/Low Selector/lowSelectorWith4Input.js
@@ -0,0 +1,137 @@
+
+
+Identify_H2L_LS4Input = function(hlselectorType, hlselectorInput, jsonarray){
+/* var reader = new draw2d.io.json.Reader();
+ reader.unmarshal(canvas1, json); */
+
+
+ // app = new example.Application(hlselectorType, hlselectorInput, jsonarray);
+
+
+ Low_4Input_RightSelector = 0;
+
+ Low_4Input_WrongSelector = 0;
+
+ var temp = JSON.parse(jsonarray);
+
+// console.log(temp);
+
+ var temp1 = 0;
+
+
+
+$.each(temp , function (key, value) {
+ if(value.type == "draw2d.SetFigure"){
+
+ temp1 = 1;
+
+ }
+
+});
+
+
+
+ if(temp1 != 0){
+
+ for(i= 0; i < temp.length; i++){
+
+ if(temp[i].type == "draw2d.SetFigure"){
+
+
+ if(temp[i].id == "lowselector_4input"){
+
+ Low_4Input_RightSelector = 1;
+
+
+ } else{
+
+ Low_4Input_WrongSelector = 1;
+ CheckWrongConnectionH2L_LS4Input();
+ break;
+
+ }
+
+
+ }
+
+ }
+
+ CheckRightConnectionH2L_LS4Input();
+
+ }else{
+
+ alertify.alert("Please select right symbol to identify");
+
+ }
+
+
+
+
+}
+
+CheckRightConnectionH2L_LS4Input = function(){
+
+ if(Low_4Input_RightSelector == 1 && Low_4Input_WrongSelector == 0){
+
+ alertify.alert("Identification is successful.
Please click next level");
+ app.toolbar.characterisation_Button.show();
+// app.toolbar.characterisation_Button.hide();
+ rightConn = 1;
+
+ }else{
+
+ if(Low_4Input_WrongSelector == 0){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+ }else{
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++
+ rightConn = 0;
+ }
+
+
+
+ }
+
+
+ }
+
+}
+
+CheckWrongConnectionH2L_LS4Input = function(){
+
+
+ if(ConnFlagCnt == 3){
+ app.toolbar.hintButton.show();
+
+ alertify.alert("Wrong identification");
+ rightConn = 0;
+
+
+ }else{
+
+ if(Low_4Input_WrongSelector == 1){
+
+ alertify.alert("Wrong identification");
+ ConnFlagCnt++;
+ rightConn = 0;
+
+ }
+ }
+
+
+
+
+
+
+
+}
+
+
+
+
diff --git a/experiment/simulation/js/H2L_discription/discription.js b/experiment/simulation/js/H2L_discription/discription.js
new file mode 100644
index 0000000..58523a2
--- /dev/null
+++ b/experiment/simulation/js/H2L_discription/discription.js
@@ -0,0 +1,75 @@
+
+showDiscription = function(number) {
+
+ $(".levelsApp").css("padding","5px");
+ //$(".levelsApp").hide();
+ $("#tramsTInst").hide();
+ if (number == "1") {
+
+ var LC_discription = '';
+ LC_discription += '
'
+ + '
Level Control Theory '
+ + '
A level (H) in tank (T100) containing liquid is to be controlled by adjusting the OUT FLOW OR IN FLOW depending on the control strategy prescribed by the control expert.
The level in the tank is measured using a level sensor (LE 100). The output of the sensor is converted into instrument standard viz. 4~20 mA/HART/FF using a level transmitter (LT 100).
The output of the transmitter will be based on the selection of the configuration of the transmitter i.e. it can be 4~20 mA, HART or FF signal.
The output of the transmitter is connected to a PID controller (LIC 100/LIC 200).
As per the output of the controller the I/P converter (LY 100/LY 200) will send corresponding pneumatic signal to the control valve (LCV 100/LCV 200).
It is pertinent to note that the accuracy of the controller will be dependant of the accuracy of the sensing and transmitting signal. The configuration and calibration of the transmitter becomes essential to achieve the best results.
Hence in this experiment you are required to select/configure/calibrate level transmitter.
'
+ + '
';
+
+
+
+ //$("#tramsTInst").hide();
+ $("#appName").html('');
+ $("#appName")
+ .html('
Calibration and fault finding of current to pneumatic converter ');
+ $("#TestDiv").html('');
+ $("#TestDiv").html(LC_discription);
+
+ } else if (number == "2") {
+
+ var TC_discription = '';
+ TC_discription +='
'
+ +'
Temperature Control Theory '
+ +'
The example is of a typical “Continuous Stirred Tank Reactor†(CSTR).
Temperature in the tank (T100) containing liquid is to be controlled by adjusting the IN FLOW of the steam, based on the control strategy prescribed by the control expert.
The temperature in the tank is measured using a temperature sensor (TE 100).
The output of the sensor is converted into instrument standard viz. 4~20 mA/HART/FF using a temperature transmitter (TT 100).
The output of the transmitter will be based on the selection of the configuration of the transmitter i.e. it can be 4~20 mA, HART or FF signal.
The output of the transmitter is connected to a PID controller (TIC 100).
As per the output of the controller the I/P converter (TY 100) will send corresponding pneumatic signal to the control valve (TCV 100).
It is pertinent to note that the accuracy of the controller will be dependant of the accuracy of the sensing and transmitting signal.
The configuration and calibration of the transmitter becomes essential to achieve the best results. Hence in this experiment you are required to select/configure/calibrate level transmitter.
'
+ +'
';
+
+ //$("#tramsTInst").hide();
+ $("#appName").html('');
+ $("#appName")
+ .html(
+ '
Calibration and fault finding of current to pneumatic converter ');
+ $("#TestDiv").html('');
+ $("#TestDiv").html(TC_discription);
+
+ } else if (number == "3") {
+
+ var PC_discription = '';
+ PC_discription += '
'
+ + '
Pressure Control Theory '
+ + '
The example is of a typical pressure control in a reservoir.
Temperature in the tank (T100) containing gas is to be controlled by adjusting the IN FLOW of the gas, based on the control strategy prescribed by the control expert.
The pressure in the tank is measured using a pressure sensor (PE 100).
The output of the sensor is converted into instrument standard viz. 4~20 mA/HART/FF using a pressure transmitter (PT 100).
The output of the transmitter will be based on the selection of the configuration of the transmitter i.e. it can be 4~20 mA, HART or FF signal.
The output of the transmitter is connected to a PID controller (PIC 100).
As per the output of the controller the I/P converter (PY 100) will send corresponding pneumatic signal to the control valve (PCV 100).
It is pertinent to note that the accuracy of the controller will be dependant of the accuracy of the sensing and transmitting signal.
The configuration and calibration of the transmitter becomes essential to achieve the best results.
Hence in this experiment you are required to select/configure/calibrate level transmitter.
'
+ + '
';
+ //$("#tramsTInst").hide();
+ $("#appName").html('');
+ $("#appName")
+ .html(
+ '
Calibration and fault finding of current to pneumatic converter ');
+ $("#TestDiv").html('');
+ $("#TestDiv").html(PC_discription);
+
+ } else if (number == "4") {
+
+ var FC_discription = '';
+ FC_discription += '
'
+ + '
Flow Control Theory '
+ + '
The example is of a typical “distribution systemâ€, wherein as per user demand the flow will be supplied to user.
Flow is measured using an orifice plate (FE 100).
As the relation between the differential pressure and flow is square root, a square root extractor needs to be configured in the transmitter.
Based on this signal and the control strategy prescribed by the control expert the output control valve (FCV 100).
The output of the sensor is converted into instrument standard viz. 4~20 mA/HART/FF using a flow transmitter (FT 100).
The output of the transmitter will be based on the selection of the configuration of the transmitter i.e. it can be 4~20 mA, HART or FF signal.
The output of the transmitter is connected to a PID controller (FIC 100).
As per the output of the controller the I/P converter (FY 100) will send corresponding pneumatic signal to the control valve (FCV 100).
It is pertinent to note that the accuracy of the controller will be dependant of the accuracy of the sensing and transmitting signal.
The configuration and calibration of the transmitter becomes essential to achieve the best results.
Hence in this experiment you are required to select/configure/calibrate level transmitter.
'
+ + '
';
+ //$("#tramsTInst").hide();
+ $("#appName").html('');
+ $("#appName")
+ .html(
+ '
Calibration and fault finding of current to pneumatic converter ');
+ $("#TestDiv").html('');
+ $("#TestDiv").html(FC_discription);
+
+ } else {
+
+ $("#TestDiv").html('');
+ }
+
+}
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/Application.js b/experiment/simulation/js/H2L_src/Application.js
new file mode 100644
index 0000000..060ad19
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/Application.js
@@ -0,0 +1,28 @@
+// declare the namespace for this example
+var example = {};
+
+/**
+ *
+ * The **GraphicalEditor** is responsible for layout and dialog handling.
+ *
+ * @author Andreas Herz
+ * @extends draw2d.ui.parts.GraphicalEditor
+ */
+example.Application = Class.extend(
+{
+ NAME : "example.Application",
+
+ /**
+ * @constructor
+ *
+ * @param {String} canvasId the id of the DOM element to use as paint container
+ */
+ init : function(hlselectorType, hlselectorInput, limitValue)
+ {
+ this.view = new example.View("draw2Did");
+ this.toolbar = new example.Toolbar("toolbar", this.view, hlselectorType, hlselectorInput, limitValue);
+
+
+
+ }
+});
diff --git a/experiment/simulation/js/H2L_src/Calculation.js b/experiment/simulation/js/H2L_src/Calculation.js
new file mode 100644
index 0000000..235e9c1
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/Calculation.js
@@ -0,0 +1,15 @@
+$(document).ready(function() {
+
+
+
+
+ H2L_Configure();
+
+ ExpTrackData = {};
+
+
+
+
+
+
+});
diff --git a/experiment/simulation/js/H2L_src/HoverConnection.js b/experiment/simulation/js/H2L_src/HoverConnection.js
new file mode 100644
index 0000000..c819141
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/HoverConnection.js
@@ -0,0 +1,44 @@
+var HoverConnection = draw2d.Connection.extend({
+
+ init: function ( sourcePort, targetPort) {
+ var self = this;
+ this._super({
+ router: new draw2d.layout.connection.InteractiveManhattanConnectionRouter(),
+ radius: 3,
+ source: sourcePort,
+ target: targetPort,
+ color: "#00a8f0",
+ stroke: 1.35,
+ //sourceDecorator: new draw2d.decoration.connection.ArrowDecorator(0,10),
+ //targetDecorator: new draw2d.decoration.connection.ArrowDecorator(0,10),
+ });
+
+ /* this.on("dragEnter", function (emitter, event) {
+ self.attr({
+ outlineColor: "#303030",
+ outlineStroke: 2,
+ color: "#00a8f0"
+ });
+ });
+ this.on("dragLeave", function (emitter, event) {
+ self.attr({
+ outlineColor: "#303030",
+ outlineStroke: 0,
+ color: "#000000"
+ });
+ });*/
+ },
+
+ /**
+ * required to receive dragEnter/dragLeave request.
+ * This figure ignores drag/drop events if it is not a valid target
+ * for the draggedFigure
+ *
+ * @param draggedFigure
+ * @returns {HoverConnection}
+ */
+ delegateTarget: function(draggedFigure)
+ {
+ return this;
+ }
+});
diff --git a/experiment/simulation/js/H2L_src/SymbolLiabrary.js b/experiment/simulation/js/H2L_src/SymbolLiabrary.js
new file mode 100644
index 0000000..089548f
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/SymbolLiabrary.js
@@ -0,0 +1,268 @@
+//var SINGLEACTINGCYLINDER = SINGLEACTINGCYLINDER || {};
+
+
+$(function () {
+
+// SINGLEACTINGCYLINDER.connectionLevel = function(hlselectorType, hlselectorInput, limitValue){
+
+ connectionLevel = function(hlselectorType, hlselectorInput, limitValue){
+
+// console.log(hlselectorType, hlselectorInput, limitValue);
+
+ ConnFlagCnt = 0;
+ rightConn = 0;
+ $("#mainDiv").html('');
+
+ var SymbolLibrary = '';
+
+ SymbolLibrary+='
'
+
+ +'
'
+ +'
'
+ +'
Library '
+ // Common Symbols
+ +'
'
+ +'
Common Symbols
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ +'
'
+ +'
Transmitter Symbols
'
+ // LT Symbols
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ //TT Symbols
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ // PT Symbols
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ //FT Symbols
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ //I2P symbols
+ +'
'
+ +'
I/P Converter Symbols
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ +'
'
+ +'
P/E Converter Symbols
'
+ // Pneumatic Transmitter Symbols
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ // P/E Converter Symbols
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ +'
'
+ +'
High Low Selecter Symbols
'
+ // H2L Selector Symbol
+
+ // High Selector Symbols
+ +'
'
+ +'
'
+ +'
'
+ // Low Selector Symbols
+ +'
'
+ +'
'
+ +'
'
+ // RateLimiter, High Limit, Low limit symbols
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+
+ +'
'
+ +'
'
+ +'
'
+ //+'Check Connections '
+ +' '
+ +'
'
+
+ //+'
Connections '
+ +''
+
+ +'
';
+
+ $("#mainDiv").html(SymbolLibrary);
+
+
+ app = new example.Application(hlselectorType, hlselectorInput, limitValue);
+ //var canvas = new example.View("draw2Did");
+ app.view.installEditPolicy( new draw2d.policy.connection.DragConnectionCreatePolicy({
+ createConnection: function(){
+ return new HoverConnection();
+ }
+ }));
+
+
+ $('#draw2Did').bind('contextmenu', function(e) {
+ return false;
+ });
+
+ /* var canvas = new draw2d.Canvas("draw2Did");
+ canvas.setScrollArea($(window));
+ canvas.installEditPolicy(new draw2d.policy.canvas.CoronaDecorationPolicy());
+
+ // return my special kind of connection
+ var createConnection=function(){
+
+ var con = new draw2d.Connection({
+ radius: 5,
+ router: new draw2d.layout.connection.InteractiveManhattanConnectionRouter(),
+ color: "#00a8f0",
+ stroke: 1.35
+
+ });
+ return con;
+ };
+
+// install a custom connection create policy
+
+ canvas.installEditPolicy( new draw2d.policy.connection.DragConnectionCreatePolicy({
+ createConnection: createConnection
+ }));
+
+
+ // check connection
+ $("#save").on("click", function (e) {
+ // Save flowchart
+ alertify.alert("in save");
+
+ var svg = $("#draw2Did").html();
+ var writer = new draw2d.io.json.Writer();
+ writer.marshal(canvas,function(json){
+
+ var jsonarray = JSON.stringify(json, null, 2);
+ // Save jsonarray to DB
+ alertify.alert(jsonarray);
+
+ console.log(jsonarray);
+ if(appId == 1){
+
+ checkConnectionsForLC(appId,jsonarray);
+ }
+// checkConnections(jsonarray);
+
+ });
+ });
+
+ */
+
+
+ /* $("#img1, #img2, #img3, #img4 ").draggable({
+ helper: 'clone',
+ cursor: "crosshair"
+
+ });
+
+ $("#draw2Did").droppable({
+ disabled: false,
+ accept :'#img1, #img2, #img3, #img4',
+
+ drop: function(event,ui) {
+
+ var figure = null;
+
+ console.log("pageX: " + event.pageX + ", pageY: " + event.pageY);
+
+ var draggedId = ui.draggable.prop("id");
+
+ // if(event.pageX < 700 && event.pageY < 800){
+ if(draggedId == "img1"){
+
+ newRect2 = addRect2(canvas,event.pageX,event.pageY);
+ figure = newRect2;
+
+
+
+ }else if(draggedId == "img2"){
+
+
+
+ newRec = addRec(canvas,event.pageX,event.pageY);
+ figure = newRec;
+
+
+ }else if(draggedId == "img3"){
+
+
+
+ newRect1 = addRect1(canvas,event.pageX,event.pageY);
+ figure = newRect1;
+
+
+
+ }else if(draggedId == "img4"){
+
+
+
+
+
+ }
+
+ var command = new draw2d.command.CommandAdd(canvas, figure, event.pageX , event.pageY);
+ canvas.getCommandStack().execute(command);
+
+ // }
+ //$("#design").css('border','none')
+ // $(".priCoil").css('display','none');
+ // $("#design").droppable("option", "disabled", true );
+
+ }
+ });
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+
+});
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/Toolbar.js b/experiment/simulation/js/H2L_src/Toolbar.js
new file mode 100644
index 0000000..25cb79f
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/Toolbar.js
@@ -0,0 +1,209 @@
+
+example.Toolbar = Class.extend({
+
+ init:function(elementId, view, hlselectorType, hlselectorInput, limitValue){
+ this.html = $("#"+elementId);
+ this.view = view;
+
+ var jsonarray;
+
+ /* // register this class as event listener for the canvas
+ // CommandStack. This is required to update the state of
+ // the Undo/Redo Buttons.
+ //
+ view.getCommandStack().addEventListener(this);
+*/
+ // Register a Selection listener for the state hnadling
+ // of the Delete Button
+ //
+ view.on("select", $.proxy(this.onSelectionChanged,this));
+
+ /* // Inject the UNDO Button and the callbacks
+ //
+ this.undoButton = $("
Undo ");
+ this.html.append(this.undoButton);
+ this.undoButton.button().click($.proxy(function(){
+ this.view.getCommandStack().undo();
+ },this)).button( "option", "disabled", true );
+
+ // Inject the REDO Button and the callback
+ //
+ this.redoButton = $("
Redo ");
+ this.html.append(this.redoButton);
+ this.redoButton.button().click($.proxy(function(){
+ this.view.getCommandStack().redo();
+ },this)).button( "option", "disabled", true );
+
+ this.delimiter = $("
");
+ this.html.append(this.delimiter);
+*/
+
+
+
+
+ // Inject Check Connection Button
+ this.checkButton = $("
Identify Symbol ");
+ this.html.append(this.checkButton);
+ this.checkButton.button().click(function(){
+
+ var svg = $("#draw2Did").html();
+ var writer = new draw2d.io.json.Writer();
+ writer.marshal(view,function(json){
+
+ jsonarray = JSON.stringify(json, null, 2);
+ // Save jsonarray to
+// console.log(jsonarray);
+ checkConnectionsForH2L(hlselectorType, hlselectorInput, limitValue,jsonarray);
+
+
+ });
+ })
+
+
+ // Inject the DELETE Button
+ //
+ this.deleteButton = $("
Delete ");
+ this.html.append(this.deleteButton);
+ this.deleteButton.button().click($.proxy(function(){
+ var node = this.view.getPrimarySelection();
+// console.log(node);
+ var command= new draw2d.command.CommandDelete(node);
+ this.view.getCommandStack().execute(command);
+
+// if(id = "PowerSupply"){
+//
+// $("#pwrSply").draggable({ disabled: false });
+// }
+
+ },this)).button( "option", "disabled", true );
+
+
+
+ // Inject Connection Hint Button
+ this.hintButton = $("
Symbol Hint ");
+ this.html.append(this.hintButton);
+ this.hintButton.hide();
+ this.hintButton.button().click(function(){
+ ConnHint(hlselectorType, hlselectorInput, limitValue);
+ });
+
+
+
+
+
+ // Inject Next Level Button
+ this.characterisation_Button = $("
Next Level ");
+ this.html.append(this.characterisation_Button);
+ this.characterisation_Button.hide();
+ this.characterisation_Button.button().click(function(){
+// console.log(appId);
+// console.log(Type);
+// console.log(jsonarray);
+ if(rightConn != 0 ){
+
+
+ // high selector connection check
+
+ // high selector with 2 inputs connection check
+ if (hlselectorType == "high" && hlselectorInput == "2") {
+
+ Characterisation_HS2Input(hlselectorType, hlselectorInput);
+
+ }
+ // high selector with 3 inputs connection check
+ if (hlselectorType == "high" && hlselectorInput == "3") {
+
+ Characterisation_HS3Input(hlselectorType, hlselectorInput);
+
+ }
+ // high selector with 4 inputs connection check
+ if (hlselectorType == "high" && hlselectorInput == "4") {
+
+ Characterisation_HS4Input(hlselectorType, hlselectorInput);
+
+ }
+
+
+ // low selector connection check
+
+ // low selector with 2 inputs connection check
+ if (hlselectorType == "low" && hlselectorInput == "2") {
+
+ Characterisation_LS2Input(hlselectorType, hlselectorInput);
+
+ }
+ // low selector with 3 inputs connection check
+ if (hlselectorType == "low" && hlselectorInput == "3") {
+
+ Characterisation_LS3Input(hlselectorType, hlselectorInput);
+
+ }
+ // low selector with 4 inputs connection check
+ if (hlselectorType == "low" && hlselectorInput == "4") {
+
+ Characterisation_LS4Input(hlselectorType, hlselectorInput);
+
+ }
+ // Limiter selector connection check
+
+ // rate limiter connection check
+ if (hlselectorType == "ratelimiter") {
+
+ Characterisation_RLInput(hlselectorType, limitValue);
+
+ }
+ // High limiter connection check
+ if (hlselectorType == "highlimit") {
+
+ Characterisation_HLInput(hlselectorType, limitValue);
+
+ }
+ // low limiter connection check
+ if (hlselectorType == "lowlimit") {
+
+ Characterisation_LLInput(hlselectorType, limitValue);
+
+ }
+
+
+ }else{
+
+ alert("Wrong Identification. Please click Identify Symbol to verify.");
+ }
+
+
+
+
+ });
+
+
+ },
+
+ /**
+ * @method
+ * Called if the selection in the cnavas has been changed. You must register this
+ * class on the canvas to receive this event.
+ *
+ * @param {draw2d.Canvas} emitter
+ * @param {Object} event
+ * @param {draw2d.Figure} event.figure
+ */
+ onSelectionChanged : function(emitter, event){
+ this.deleteButton.button( "option", "disabled", event.figure===null );
+ },
+
+ /**
+ * @method
+ * Sent when an event occurs on the command stack. draw2d.command.CommandStackEvent.getDetail()
+ * can be used to identify the type of event which has occurred.
+ *
+ * @template
+ *
+ * @param {draw2d.command.CommandStackEvent} event
+ **/
+ /*stackChanged:function(event)
+ {
+ this.undoButton.button( "option", "disabled", !event.getStack().canUndo() );
+ this.redoButton.button( "option", "disabled", !event.getStack().canRedo() );
+ }*/
+});
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/View.js b/experiment/simulation/js/H2L_src/View.js
new file mode 100644
index 0000000..5cd19f5
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/View.js
@@ -0,0 +1,352 @@
+
+
+example.View = draw2d.Canvas.extend({
+
+ init:function(id){
+ this._super(id);
+
+ this.setScrollArea($("#draw2Did"));
+
+ this.currentDropConnection = null;
+
+
+ },
+
+ /**
+ * @method
+ * Called if the DragDrop object is moving around.
+ *
+ * Graphiti use the jQuery draggable/droppable lib. Please inspect
+ * http://jqueryui.com/demos/droppable/ for further information.
+ *
+ * @param {HTMLElement} droppedDomNode The dragged DOM element.
+ * @param {Number} x the x coordinate of the drag
+ * @param {Number} y the y coordinate of the drag
+ *
+ * @template
+ **/
+ onDrag:function(droppedDomNode, x, y )
+ {
+ },
+
+ /**
+ * @method
+ * Called if the user drop the droppedDomNode onto the canvas.
+ *
+ * Draw2D use the jQuery draggable/droppable lib. Please inspect
+ * http://jqueryui.com/demos/droppable/ for further information.
+ *
+ * @param {HTMLElement} droppedDomNode The dropped DOM element.
+ * @param {Number} x the x coordinate of the drop
+ * @param {Number} y the y coordinate of the drop
+ * @param {Boolean} shiftKey true if the shift key has been pressed during this event
+ * @param {Boolean} ctrlKey true if the ctrl key has been pressed during the event
+ * @private
+ **/
+ onDrop : function(droppedDomNode, x, y)
+ {
+ var figure;
+ var type = $(droppedDomNode).data("shape");
+
+ //Comman Symbols
+ if(type == "pwrSply"){
+
+ powersupply = powerSupply(this,x,y);
+ figure = powersupply;
+ // $("#pwrSply").draggable({ disabled: true });
+ }
+
+ if(type == "signal"){
+
+ signl = signal(this,x,y);
+ figure = signl;
+ }
+
+ if(type == "configurator"){
+
+ configurator = Configurator(this,x,y);
+ figure = configurator;
+ }
+ if(type == "fftCard"){
+
+ fft_Card = fftCard(this,x,y);
+ figure = fft_Card;
+ }
+
+ if(type == "analogOut"){
+
+ analogOut = AnalogOut(this,x,y);
+ figure = analogOut;
+
+ }
+
+
+ // LT TRANSMITTER TYPES
+ if(type == "LT_twoWireTrsmtr"){
+
+ twoWireTransmitter_lt = TwoWireTransmitter_LT(this,x,y);
+ figure = twoWireTransmitter_lt;
+ }
+
+ if(type == "LT_threeWireTrsmtr"){
+
+ threeWireTransmitter_lt = ThreeWireTransmitter_LT(this,x,y);
+ figure = threeWireTransmitter_lt;
+ }
+ if(type == "LT_fourWireTrsmtr"){
+
+ fourWireTransmitter_lt = FourWireTransmitter_LT(this,x,y);
+ figure = fourWireTransmitter_lt;
+ }
+ if(type == "LT_hartTrsmtr"){
+
+ hartTransmitter_lt = HartTransmitter_LT(this,x,y);
+ figure = hartTransmitter_lt;
+ }
+ if(type == "LT_FFTrsmtr"){
+
+ fft_Transmitter_lt = FFT_Transmitter_LT(this,x,y);
+ figure = fft_Transmitter_lt;
+ }
+
+
+ // TT TRANSMITTER TYPES
+ if(type == "TT_twoWireTrsmtr"){
+
+ twoWireTransmitter_tt = TwoWireTransmitter_TT(this,x,y);
+ figure = twoWireTransmitter_tt;
+ }
+
+ if(type == "TT_threeWireTrsmtr"){
+
+ threeWireTransmitter_tt = ThreeWireTransmitter_TT(this,x,y);
+ figure = threeWireTransmitter_tt;
+ }
+ if(type == "TT_fourWireTrsmtr"){
+
+ fourWireTransmitter_tt = FourWireTransmitter_TT(this,x,y);
+ figure = fourWireTransmitter_tt;
+ }
+ if(type == "TT_hartTrsmtr"){
+
+ hartTransmitter_tt = HartTransmitter_TT(this,x,y);
+ figure = hartTransmitter_tt;
+ }
+ if(type == "TT_FFTrsmtr"){
+
+ fft_Transmitter_tt = FFT_Transmitter_TT(this,x,y);
+ figure = fft_Transmitter_tt;
+ }
+
+
+ // PT TRANSMITTER TYPES
+ if(type == "PT_twoWireTrsmtr"){
+
+ twoWireTransmitter_pt = TwoWireTransmitter_PT(this,x,y);
+ figure = twoWireTransmitter_pt;
+ }
+
+ if(type == "PT_threeWireTrsmtr"){
+
+ threeWireTransmitter_pt = ThreeWireTransmitter_PT(this,x,y);
+ figure = threeWireTransmitter_pt;
+ }
+ if(type == "PT_fourWireTrsmtr"){
+
+ fourWireTransmitter_pt = FourWireTransmitter_PT(this,x,y);
+ figure = fourWireTransmitter_pt;
+ }
+ if(type == "PT_hartTrsmtr"){
+
+ hartTransmitter_pt = HartTransmitter_PT(this,x,y);
+ figure = hartTransmitter_pt;
+ }
+ if(type == "PT_FFTrsmtr"){
+
+ fft_Transmitter_pt = FFT_Transmitter_PT(this,x,y);
+ figure = fft_Transmitter_pt;
+ }
+
+ // FT TRANSMITTER TYPES
+ if(type == "FT_twoWireTrsmtr"){
+
+ twoWireTransmitter_ft = TwoWireTransmitter_FT(this,x,y);
+ figure = twoWireTransmitter_ft;
+ }
+
+ if(type == "FT_threeWireTrsmtr"){
+
+ threeWireTransmitter_ft = ThreeWireTransmitter_FT(this,x,y);
+ figure = threeWireTransmitter_ft;
+ }
+ if(type == "FT_fourWireTrsmtr"){
+
+ fourWireTransmitter_ft = FourWireTransmitter_FT(this,x,y);
+ figure = fourWireTransmitter_ft;
+ }
+ if(type == "FT_hartTrsmtr"){
+
+ hartTransmitter_ft = HartTransmitter_FT(this,x,y);
+ figure = hartTransmitter_ft;
+ }
+ if(type == "FT_FFTrsmtr"){
+
+ fft_Transmitter_ft = FFT_Transmitter_FT(this,x,y);
+ figure = fft_Transmitter_ft;
+ }
+
+ // I2P Converter Symbols
+
+ if(type == "LY_100"){
+
+ I2P_LY100 = I2P_LY_100(this,x,y);
+ figure = I2P_LY100;
+ }
+ if(type == "TY_100"){
+
+ I2P_TY100 = I2P_TY_100(this,x,y);
+ figure = I2P_TY100;
+ }
+ if(type == "PY_100"){
+
+ I2P_PY100 = I2P_PY_100(this,x,y);
+ figure = I2P_PY100;
+ }
+ if(type == "FY_100"){
+
+ I2P_FY100 = I2P_FY_100(this,x,y);
+ figure = I2P_FY100;
+ }
+
+ // Pneumatic Transmitter Symbols
+
+ if(type == "PT_LT_100"){
+
+ PT_LT100 = PT_LT_100(this,x,y);
+ figure = PT_LT100;
+ }
+ if(type == "PT_TT_100"){
+
+ PT_TT100 = PT_TT_100(this,x,y);
+ figure = PT_TT100;
+ }
+ if(type == "PT_PT_100"){
+
+ PT_PT100 = PT_PT_100(this,x,y);
+ figure = PT_PT100;
+ }
+ if(type == "PT_FT_100"){
+
+ PT_FT100 = PT_FT_100(this,x,y);
+ figure = PT_FT100;
+ }
+
+
+ // P/E Converter Symbols
+ if(type == "P2E_LY_100"){
+
+ P2E_LY100 = P2E_LY_100(this,x,y);
+ figure = P2E_LY100;
+ }
+ if(type == "P2E_TY_100"){
+
+ P2E_TY100 = P2E_TY_100(this,x,y);
+ figure = P2E_TY100;
+ }
+ if(type == "P2E_PY_100"){
+
+ P2E_PY100 = P2E_PY_100(this,x,y);
+ figure = P2E_PY100;
+ }
+ if(type == "P2E_FY_100"){
+
+ P2E_FY100 = P2E_FY_100(this,x,y);
+ figure = P2E_FY100;
+ }
+
+
+ // High Low Selector Symbols
+
+ // High Selector Symbols
+
+ // High selector with 2 inputs
+ if(type == "HighSelector_2_Input"){
+
+ HighSelector_2Input = HighSelector_2_Input(this,x,y);
+ figure = HighSelector_2Input;
+ }
+
+ // High selector with 3 inputs
+ if(type == "HighSelector_3_Input"){
+
+ HighSelector_3Input = HighSelector_3_Input(this,x,y);
+ figure = HighSelector_3Input;
+ }
+
+ // High selector with 4 inputs
+ if(type == "HighSelector_4_Input"){
+
+ HighSelector_4Input = HighSelector_4_Input(this,x,y);
+ figure = HighSelector_4Input;
+ }
+
+
+
+ // Low Selector Symbols
+
+ // Low selector with 2 inputs
+ if(type == "LowSelector_2_Input"){
+
+ LowSelector_2Input = LowSelector_2_Input(this,x,y);
+ figure = LowSelector_2Input;
+ }
+
+ // Low selector with 3 inputs
+ if(type == "LowSelector_3_Input"){
+
+ LowSelector_3Input = LowSelector_3_Input(this,x,y);
+ figure = LowSelector_3Input;
+ }
+
+ // Low selector with 4 inputs
+ if(type == "LowSelector_4_Input"){
+
+ LowSelector_4Input = LowSelector_4_Input(this,x,y);
+ figure = LowSelector_4Input;
+ }
+
+
+ // Limiter Symbols
+
+ //Rate Limiter
+ if(type == "Rate_Limiter"){
+
+ rate_limiter = Rate_Limiter(this,x,y);
+ figure = rate_limiter;
+ }
+
+ //High Limit
+ if(type == "High_Limit"){
+
+ high_limit = High_Limit(this,x,y);
+ figure = high_limit;
+ }
+ //Low Limit
+ if(type == "Low_Limit"){
+
+ low_limit = Low_Limit(this,x,y);
+ figure = low_limit;
+ }
+
+
+
+
+
+
+
+ // create a command for the undo/redo support
+ var command = new draw2d.command.CommandAdd(this, figure, x, y);
+ this.getCommandStack().execute(command);
+ }
+});
+
diff --git a/experiment/simulation/js/H2L_src/symbols/FTSymbols.js b/experiment/simulation/js/H2L_src/symbols/FTSymbols.js
new file mode 100644
index 0000000..1e60919
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/FTSymbols.js
@@ -0,0 +1,620 @@
+
+
+
+
+// 2 Wire Trasmitter
+
+ function TwoWireTransmitter_FT(canvas,x1,y1){
+
+ var twoWireTrans_FT = new LabeldTwoWireTrnsmtrFigure_FT({width:100,height:95});
+ twoWireTrans_FT.setId("twoWireTrans_FT");
+ twoWireTrans_FT.setResizeable(false);
+
+ var FTPort_twoWireTransPlus = twoWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ FTPort_twoWireTransPlus.setName("FT_twowireTransPlus");
+ FTPort_twoWireTransPlus.setId("FT_twowireTransPlusId");
+
+ var FTPort_twoWireTransMinus = twoWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ FTPort_twoWireTransMinus.setName("FT_twowireTransMinus");
+ FTPort_twoWireTransMinus.setId("FT_twowireTransMinusId");
+
+
+ canvas.add( twoWireTrans_FT, x1,y1);
+ return twoWireTrans_FT;
+
+ }
+
+
+ var LabeldTwoWireTrnsmtrFigure_FT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "FT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "2-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// 3 wire transmitter
+
+ function ThreeWireTransmitter_FT(canvas,x1,y1){
+
+ var threeWireTrans_FT = new LabeldThreeWireTrnsmtrFigure_FT({width:120,height:100});
+ threeWireTrans_FT.setId("threeWireTrans_FT");
+ threeWireTrans_FT.setResizeable(false);
+
+ var FTPort_threeWireTransSuplyPlus = threeWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ FTPort_threeWireTransSuplyPlus.setName("FT_threeWireTransSuplyPlus");
+ FTPort_threeWireTransSuplyPlus.setId("FT_threeWireTransSuplyPlusId");
+
+ var FTPort_threeWireTransSigPlus = threeWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ FTPort_threeWireTransSigPlus.setName("FT_threeWireTransSigPlus");
+ FTPort_threeWireTransSigPlus.setId("FT_threeWireTransSigPlusId");
+
+ var FTPort_threeWireTransMinus = threeWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,100));
+ FTPort_threeWireTransMinus.setName("FT_threeWireTransMinus");
+ FTPort_threeWireTransMinus.setId("FT_threeWireTransMinusId");
+
+
+ canvas.add( threeWireTrans_FT, x1,y1);
+ return threeWireTrans_FT;
+
+ }
+
+
+ var LabeldThreeWireTrnsmtrFigure_FT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 120, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(60, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 60, 40, "FT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 100, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 105, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(0, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(40, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 50 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(80, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 90 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 100 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 60, 5, "3-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+// 4 wire transmitter
+
+
+function FourWireTransmitter_FT(canvas,x1,y1){
+
+ var fourWireTrans_FT = new LabeldFourWireTrnsmtrFigure_FT({width:110,height:130});
+ fourWireTrans_FT.setId("fourWireTrans_FT");
+ fourWireTrans_FT.setResizeable(false);
+
+ var FTPort_fourWireTransSuplyPlus = fourWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,60));
+ FTPort_fourWireTransSuplyPlus.setName("FT_fourWireTransSuplyPlus");
+ FTPort_fourWireTransSuplyPlus.setId("FT_fourWireTransSuplyPlusId");
+
+
+ var FTPort_fourWireTransSuplyMinus = fourWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,90));
+ FTPort_fourWireTransSuplyMinus.setName("FT_fourWireTransSuplyMinus");
+ FTPort_fourWireTransSuplyMinus.setId("FT_fourWireTransSuplyMinusId");
+
+ var FTPort_fourWireTransSigPlus = fourWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,60));
+ FTPort_fourWireTransSigPlus.setName("FT_fourWireTransSigPlus");
+ FTPort_fourWireTransSigPlus.setId("FT_fourWireTransSigPlusId");
+
+ var FTPort_fourWireTransSigMinus = fourWireTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,90));
+ FTPort_fourWireTransSigMinus.setName("FT_fourWireTransSigMinus");
+ FTPort_fourWireTransSigMinus.setId("FT_fourWireTransSigMinusId");
+
+
+ canvas.add( fourWireTrans_FT, x1,y1);
+ return fourWireTrans_FT;
+
+ }
+
+
+ var LabeldFourWireTrnsmtrFigure_FT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 110, 130).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.circle(55, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 55, 40, "FT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.text( 95, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 95, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.rect(0, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(0, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 10 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 80 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 90 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 80 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+
+ this.canvas.paper.text( 55, 10, "4-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// FT HART TRANSMITTER
+
+
+function HartTransmitter_FT(canvas,x1,y1){
+
+ var hartTrans_FT = new LabeldHartTrnsmtrFigure_FT({width:100,height:105});
+ hartTrans_FT.setId("hartTrans_FT");
+ hartTrans_FT.setResizeable(false);
+
+ var FTPort_hartTransPlus = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+ FTPort_hartTransPlus.setName("FTPort_hartTransplus");
+ FTPort_hartTransPlus.setId("FTPort_hartTransplusId");
+
+
+ var FTPort_hartTransMinu = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+ FTPort_hartTransMinu.setName("FTPort_hartTransminus");
+ FTPort_hartTransMinu.setId("FTPort_hartTransminusId");
+
+
+
+
+ canvas.add( hartTrans_FT, x1,y1);
+ return hartTrans_FT;
+
+ }
+
+
+ var LabeldHartTrnsmtrFigure_FT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 100, 105).
+ attr({"stroke-width" : 0
+ });
+ this.canvas.paper.text( 50, 10, "HART Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(50, 65, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 40, "FT").attr({
+ stroke : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 12 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 58 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 72 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 50, 60, "Signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+ this.canvas.paper.text( 50, 72, "4-20mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 70, 40, 40);
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+// FFT Trasmitter
+
+ function FFT_Transmitter_FT(canvas,x1,y1){
+
+ var ffTrans_FT = new LabeldFFT_TrnsmtrFigure_FT({width:100,height:100});
+ ffTrans_FT.setId("ffTrans_FT");
+ ffTrans_FT.setResizeable(false);
+
+ var FTPort_ffTransPlus = ffTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(25,0));
+ FTPort_ffTransPlus.setName("FT_ffTransPlus");
+ FTPort_ffTransPlus.setId("FT_ffTransPlusId");
+
+
+ var FTPort_ffTransMinus = ffTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(70,0));
+ FTPort_ffTransMinus.setName("FT_ffTransMinus");
+ FTPort_ffTransMinus.setId("FT_ffTransMinusId");
+
+
+ canvas.add( ffTrans_FT, x1,y1);
+ return ffTrans_FT;
+
+ }
+
+
+ var LabeldFFT_TrnsmtrFigure_FT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 0
+ });
+
+
+
+ this.canvas.paper.rect(5, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 10 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.circle(50, 65, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 55, "FT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 52, 40, 40);
+
+ this.canvas.paper.text( 50, 98, "Foundation Field Bus ").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 110, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/experiment/simulation/js/H2L_src/symbols/HighSelectorSymbols.js b/experiment/simulation/js/H2L_src/symbols/HighSelectorSymbols.js
new file mode 100644
index 0000000..452bd6a
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/HighSelectorSymbols.js
@@ -0,0 +1,404 @@
+
+ // High selector with 2 inputs
+
+
+function HighSelector_2_Input(canvas,x1,y1){
+
+ var highselector_2input = new LabeldHighSelectorFigure_2Input({width:130,height:130});
+ highselector_2input.setId("highselector_2input");
+ highselector_2input.setResizeable(false);
+
+// var FTPort_hartTransPlus = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+// FTPort_hartTransPlus.setName("FTPort_hartTransplus");
+// FTPort_hartTransPlus.setId("FTPort_hartTransplusId");
+//
+//
+// var FTPort_hartTransMinu = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+// FTPort_hartTransMinu.setName("FTPort_hartTransminus");
+// FTPort_hartTransMinu.setId("FTPort_hartTransminusId");
+
+
+
+
+ canvas.add( highselector_2input, x1,y1);
+ return highselector_2input;
+
+ }
+
+
+ var LabeldHighSelectorFigure_2Input = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, 7, "High Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 88 23 l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 65 l 30 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 75, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ this.canvas.paper.path("M 60 130 l 0 -38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 70, 120, "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+
+
+ // High selector with 3 inputs
+
+
+ function HighSelector_3_Input(canvas,x1,y1){
+
+ var highselector_3input = new LabeldHighSelectorFigure_3Input({width:130,height:130});
+ highselector_3input.setId("highselector_3input");
+ highselector_3input.setResizeable(false);
+
+
+
+ canvas.add( highselector_3input, x1,y1);
+ return highselector_3input;
+
+ }
+
+
+ var LabeldHighSelectorFigure_3Input = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, -10, "High Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 88 23 l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 65 l 30 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 75, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ this.canvas.paper.path("M 60 130 l 0 -38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 70, 120, "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // c input
+ this.canvas.paper.path("M 60 0 l 0 38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 50, 10, "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+
+
+ // High selector with 4 inputs
+
+
+ function HighSelector_4_Input(canvas,x1,y1){
+
+ var highselector_4input = new LabeldHighSelectorFigure_4Input({width:130,height:130});
+ highselector_4input.setId("highselector_4input");
+ highselector_4input.setResizeable(false);
+
+
+
+ canvas.add( highselector_4input, x1,y1);
+ return highselector_4input;
+
+ }
+
+
+ var LabeldHighSelectorFigure_4Input = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, -10, "High Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 88 23 l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 35 l 33 18").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 53, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+
+ // d input
+ this.canvas.paper.path("M 0 110 l 38 -28").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 18, 110, "d").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ // b input
+ this.canvas.paper.path("M 60 130 l 0 -38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 70, 120, "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // c input
+ this.canvas.paper.path("M 60 0 l 0 38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 50, 10, "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/symbols/I2PSymbols.js b/experiment/simulation/js/H2L_src/symbols/I2PSymbols.js
new file mode 100644
index 0000000..8c612dc
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/I2PSymbols.js
@@ -0,0 +1,409 @@
+
+
+
+// I2p LY symbol
+
+ function I2P_LY_100(canvas,x1,y1){
+
+ var LY100_i2p = new LabeldFigure_LY100({width:100,height:95});
+ LY100_i2p.setId("LY100_i2p");
+ LY100_i2p.setResizeable(false);
+
+ var LY100Port_i2pPlus = LY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ LY100Port_i2pPlus.setName("LY100_i2pPlus");
+ LY100Port_i2pPlus.setId("LY100_i2pPlusId");
+
+
+ var LY100Port_i2pMinus = LY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ LY100Port_i2pMinus.setName("LY100_i2pMinus");
+ LY100Port_i2pMinus.setId("LY100_i2pMinusId");
+
+
+ canvas.add( LY100_i2p, x1,y1);
+ return LY100_i2p;
+
+ }
+
+
+ var LabeldFigure_LY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "LY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "I/P Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+ // I2p TY symbol
+
+ function I2P_TY_100(canvas,x1,y1){
+
+ var TY100_i2p = new LabeldFigure_TY100({width:100,height:95});
+ TY100_i2p.setId("TY100_i2p");
+ TY100_i2p.setResizeable(false);
+
+ var TY100Port_i2pPlus = TY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ TY100Port_i2pPlus.setName("TY100_i2pPlus");
+ TY100Port_i2pPlus.setId("TY100_i2pPlusId");
+
+
+ var TY100Port_i2pMinus = TY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ TY100Port_i2pMinus.setName("TY100_i2pMinus");
+ TY100Port_i2pMinus.setId("TY100_i2pMinusId");
+
+
+ canvas.add( TY100_i2p, x1,y1);
+ return TY100_i2p;
+
+ }
+
+ var LabeldFigure_TY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "TY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "I/P Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+
+ // I2p PY symbol
+
+ function I2P_PY_100(canvas,x1,y1){
+
+ var PY100_i2p = new LabeldFigure_PY100({width:100,height:95});
+ PY100_i2p.setId("PY100_i2p");
+ PY100_i2p.setResizeable(false);
+
+ var PY100Port_i2pPlus = PY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ PY100Port_i2pPlus.setName("PY100_i2pPlus");
+ PY100Port_i2pPlus.setId("PY100_i2pPlusId");
+
+
+ var PY100Port_i2pMinus = PY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ PY100Port_i2pMinus.setName("PY100_i2pMinus");
+ PY100Port_i2pMinus.setId("PY100_i2pMinusId");
+
+
+ canvas.add( PY100_i2p, x1,y1);
+ return PY100_i2p;
+
+ }
+
+
+ var LabeldFigure_PY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "PY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "I/P Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+ // I2p FY symbol
+
+ function I2P_FY_100(canvas,x1,y1){
+
+ var FY100_i2p = new LabeldFigure_FY100({width:100,height:95});
+ FY100_i2p.setId("FY100_i2p");
+ FY100_i2p.setResizeable(false);
+
+ var FY100Port_i2pPlus = FY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ FY100Port_i2pPlus.setName("FY100_i2pPlus");
+ FY100Port_i2pPlus.setId("FY100_i2pPlusId");
+
+
+ var FY100Port_i2pMinus = FY100_i2p.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ FY100Port_i2pMinus.setName("FY100_i2pMinus");
+ FY100Port_i2pMinus.setId("FY100_i2pMinusId");
+
+
+ canvas.add( FY100_i2p, x1,y1);
+ return FY100_i2p;
+
+ }
+
+
+ var LabeldFigure_FY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "FY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "I/P Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
diff --git a/experiment/simulation/js/H2L_src/symbols/LTSymbols.js b/experiment/simulation/js/H2L_src/symbols/LTSymbols.js
new file mode 100644
index 0000000..83b55e4
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/LTSymbols.js
@@ -0,0 +1,680 @@
+
+
+
+// 2 Wire Trasmitter
+
+ function TwoWireTransmitter_LT(canvas,x1,y1){
+
+ var twoWireTrans_LT = new LabeldTwoWireTrnsmtrFigure_LT({width:100,height:95});
+ twoWireTrans_LT.setId("twoWireTrans_LT");
+ twoWireTrans_LT.setResizeable(false);
+
+ var LTPort_twoWireTransPlus = twoWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ LTPort_twoWireTransPlus.setName("LT_twowireTransPlus");
+ LTPort_twoWireTransPlus.setId("LT_twowireTransPlusId");
+
+
+ var LTPort_twoWireTransMinus = twoWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ LTPort_twoWireTransMinus.setName("LT_twowireTransMinus");
+ LTPort_twoWireTransMinus.setId("LT_twowireTransMinusId");
+
+
+ canvas.add( twoWireTrans_LT, x1,y1);
+ return twoWireTrans_LT;
+
+ }
+
+
+ var LabeldTwoWireTrnsmtrFigure_LT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "LT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "2-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// 3 wire transmitter
+
+ function ThreeWireTransmitter_LT(canvas,x1,y1){
+
+ var threeWireTrans_LT = new LabeldThreeWireTrnsmtrFigure_LT({width:120,height:100});
+ threeWireTrans_LT.setId("threeWireTrans_LT");
+ threeWireTrans_LT.setResizeable(false);
+
+ var LTPort_threeWireTransSuplyPlus = threeWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ LTPort_threeWireTransSuplyPlus.setName("LT_threeWireTransSuplyPlus");
+ LTPort_threeWireTransSuplyPlus.setId("LT_threeWireTransSuplyPlusId");
+
+ var LTPort_threeWireTransSigPlus = threeWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ LTPort_threeWireTransSigPlus.setName("LT_threeWireTransSigPlus");
+ LTPort_threeWireTransSigPlus.setId("LT_threeWireTransSigPlusId");
+
+ var LTPort_threeWireTransMinus = threeWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,100));
+ LTPort_threeWireTransMinus.setName("LT_threeWireTransMinus");
+ LTPort_threeWireTransMinus.setId("LT_threeWireTransMinusId");
+
+
+ canvas.add( threeWireTrans_LT, x1,y1);
+ return threeWireTrans_LT;
+
+ }
+
+
+ var LabeldThreeWireTrnsmtrFigure_LT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 120, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(60, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 60, 40, "LT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 100, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 105, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.rect(0, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(40, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 50 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(80, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 90 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 100 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 60, 5, "3-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+// 4 wire transmitter
+
+
+function FourWireTransmitter_LT(canvas,x1,y1){
+
+ var fourWireTrans_LT = new LabeldFourWireTrnsmtrFigure_LT({width:110,height:130});
+ fourWireTrans_LT.setId("fourWireTrans_LT");
+ fourWireTrans_LT.setResizeable(false);
+
+ var LTPort_fourWireTransSuplyPlus = fourWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,60));
+ LTPort_fourWireTransSuplyPlus.setName("LT_fourWireTransSuplyPlus");
+ LTPort_fourWireTransSuplyPlus.setId("LT_fourWireTransSuplyPlusId");
+
+
+ var LTPort_fourWireTransSuplyMinus = fourWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,90));
+ LTPort_fourWireTransSuplyMinus.setName("LT_fourWireTransSuplyMinus");
+ LTPort_fourWireTransSuplyMinus.setId("LT_fourWireTransSuplyMinusId");
+
+ var LTPort_fourWireTransSigPlus = fourWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,60));
+ LTPort_fourWireTransSigPlus.setName("LT_fourWireTransSigPlus");
+ LTPort_fourWireTransSigPlus.setId("LT_fourWireTransSigPlusId");
+
+ var LTPort_fourWireTransSigMinus = fourWireTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,90));
+ LTPort_fourWireTransSigMinus.setName("LT_fourWireTransSigMinus");
+ LTPort_fourWireTransSigMinus.setId("LT_fourWireTransSigMinusId");
+
+
+ canvas.add( fourWireTrans_LT, x1,y1);
+ return fourWireTrans_LT;
+
+ }
+
+
+ var LabeldFourWireTrnsmtrFigure_LT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 110, 130).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.circle(55, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 55, 40, "LT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.text( 95, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 95, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(0, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(0, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 10 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 80 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 90 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 80 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+
+ this.canvas.paper.text( 55, 10, "4-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+// LT HART TRANSMITTER
+
+
+function HartTransmitter_LT(canvas,x1,y1){
+
+ var hartTrans_LT = new LabeldHartTrnsmtrFigure_LT({width:100,height:105});
+ hartTrans_LT.setId("hartTrans_LT");
+ hartTrans_LT.setResizeable(false);
+
+ var LTPort_hartTransPlus = hartTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+ LTPort_hartTransPlus.setName("LTPort_hartTransplus");
+ LTPort_hartTransPlus.setId("LTPort_hartTransplusId");
+
+
+ var LTPort_hartTransMinu = hartTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+ LTPort_hartTransMinu.setName("LTPort_hartTransminus");
+ LTPort_hartTransMinu.setId("LTPort_hartTransminusId");
+
+
+
+
+ canvas.add( hartTrans_LT, x1,y1);
+ return hartTrans_LT;
+
+ }
+
+
+ var LabeldHartTrnsmtrFigure_LT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 100, 105).
+ attr({"stroke-width" : 0
+ });
+ this.canvas.paper.text( 50, 10, "HART Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(50, 65, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 40, "LT").attr({
+ stroke : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 12 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 58 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 72 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 50, 60, "Signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+ this.canvas.paper.text( 50, 72, "4-20mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 70, 40, 40);
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+// FFT Trasmitter
+
+ function FFT_Transmitter_LT(canvas,x1,y1){
+
+ var ffTrans_LT = new LabeldFFT_TrnsmtrFigure_LT({width:100,height:120});
+ ffTrans_LT.setId("ffTrans_LT");
+ ffTrans_LT.setResizeable(false);
+
+ var LTPort_ffTransPlus = ffTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(25,0));
+ LTPort_ffTransPlus.setName("LT_ffTransPlus");
+ LTPort_ffTransPlus.setId("LT_ffTransPlusId");
+
+
+ var LTPort_ffTransMinus = ffTrans_LT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(70,0));
+ LTPort_ffTransMinus.setName("LT_ffTransMinus");
+ LTPort_ffTransMinus.setId("LT_ffTransMinusId");
+
+
+ canvas.add( ffTrans_LT, x1,y1);
+ return ffTrans_LT;
+
+ }
+
+
+ var LabeldFFT_TrnsmtrFigure_LT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 120).
+ attr({"stroke-width" : 1
+ });
+
+
+
+ this.canvas.paper.rect(5, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 10 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.circle(50, 65, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 55, "LT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 52, 40, 40);
+
+ this.canvas.paper.text( 50, 98, "Foundation Field Bus ").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 110, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*var SelectionMenuPolicy = draw2d.policy.figure.SelectionPolicy.extend({
+ NAME: "SelectionMenuPolicy",
+
+ init : function(attr, setter, getter)
+ {
+ this.overlay = null; // div DOM node
+
+ this._super(attr, setter, getter);
+ },
+
+
+ onSelect: function(canvas, figure, isPrimarySelection)
+ {
+ this._super(canvas, figure, isPrimarySelection);
+
+ if (this.overlay === null) {
+ this.overlay= $("");
+ $("body").append(this.overlay);
+ this.overlay.on("click",function(){
+
+ // use a Command and CommandStack for undo/redo support
+ //
+ var command= new draw2d.command.CommandDelete(figure);
+ canvas.getCommandStack().execute(command);
+
+ })
+ }
+ this.posOverlay(figure);
+ },
+
+
+ onUnselect: function(canvas, figure )
+ {
+ this._super(canvas, figure);
+
+ this.overlay.remove();
+ this.overlay=null;
+ },
+
+
+ onDrag: function(canvas, figure)
+ {
+ this._super(canvas, figure);
+ this.posOverlay(figure);
+ },
+
+ posOverlay:function(figure)
+ {
+ this.overlay.css({
+ "top":figure.getAbsoluteY()-10,
+ "left":figure.getAbsoluteX()+ figure.getWidth()+15
+ });
+ }
+});*/
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/symbols/LimiterSymbols.js b/experiment/simulation/js/H2L_src/symbols/LimiterSymbols.js
new file mode 100644
index 0000000..af55160
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/LimiterSymbols.js
@@ -0,0 +1,364 @@
+
+ //Rate Limiter
+
+
+function Rate_Limiter(canvas,x1,y1){
+
+ var selector_ratelimiter = new LabeldSelectorFigure_Ratelimiter({width:130,height:130});
+ selector_ratelimiter.setId("selector_ratelimiter");
+ selector_ratelimiter.setResizeable(false);
+
+// var FTPort_hartTransPlus = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+// FTPort_hartTransPlus.setName("FTPort_hartTransplus");
+// FTPort_hartTransPlus.setId("FTPort_hartTransplusId");
+//
+//
+// var FTPort_hartTransMinu = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+// FTPort_hartTransMinu.setName("FTPort_hartTransminus");
+// FTPort_hartTransMinu.setId("FTPort_hartTransminusId");
+
+
+
+
+ canvas.add( selector_ratelimiter, x1,y1);
+ return selector_ratelimiter;
+
+ }
+
+
+ var LabeldSelectorFigure_Ratelimiter = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, 7, "Rate Limiter").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 87 25 l 8 12 l 8 -12").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 86 30 l 18 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 65 l 30 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 75, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 60, 102, "x").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+ //High Limiter
+
+
+ function High_Limit(canvas,x1,y1){
+
+ var selector_highlimit = new LabeldSelectorFigure_Highlimit({width:130,height:130});
+ selector_highlimit.setId("selector_highlimit");
+ selector_highlimit.setResizeable(false);
+
+// var FTPort_hartTransPlus = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+// FTPort_hartTransPlus.setName("FTPort_hartTransplus");
+// FTPort_hartTransPlus.setId("FTPort_hartTransplusId");
+//
+//
+// var FTPort_hartTransMinu = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+// FTPort_hartTransMinu.setName("FTPort_hartTransminus");
+// FTPort_hartTransMinu.setId("FTPort_hartTransminusId");
+
+
+
+
+ canvas.add( selector_highlimit, x1,y1);
+ return selector_highlimit;
+
+ }
+
+
+ var LabeldSelectorFigure_Highlimit = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, 7, "High Limit").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 88 23 l 12 8 l -12 8").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 95 23 l 0 16 ").
+ attr({"stroke-width" : 2
+ });
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 65 l 30 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 75, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 60, 102, "x").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+ //Low Limiter
+
+
+ function Low_Limit(canvas,x1,y1){
+
+ var selector_lowlimit = new LabeldSelectorFigure_Lowlimit({width:130,height:130});
+ selector_lowlimit.setId("selector_lowlimit");
+ selector_lowlimit.setResizeable(false);
+
+// var FTPort_hartTransPlus = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+// FTPort_hartTransPlus.setName("FTPort_hartTransplus");
+// FTPort_hartTransPlus.setId("FTPort_hartTransplusId");
+//
+//
+// var FTPort_hartTransMinu = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+// FTPort_hartTransMinu.setName("FTPort_hartTransminus");
+// FTPort_hartTransMinu.setId("FTPort_hartTransminusId");
+
+
+
+
+ canvas.add( selector_lowlimit, x1,y1);
+ return selector_lowlimit;
+
+ }
+
+
+ var LabeldSelectorFigure_Lowlimit = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, 7, "Low Limit").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // high symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 100 23 l -12 8 l 12 8").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 92 23 l 0 16 ").
+ attr({"stroke-width" : 2
+ });
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 65 l 30 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 75, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 60, 102, "x").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/symbols/LowSelectorSymbols.js b/experiment/simulation/js/H2L_src/symbols/LowSelectorSymbols.js
new file mode 100644
index 0000000..ce14807
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/LowSelectorSymbols.js
@@ -0,0 +1,403 @@
+
+ // Low selector with 2 inputs
+
+
+function LowSelector_2_Input(canvas,x1,y1){
+
+ var lowselector_2input = new LabeldLowSelectorFigure_2Input({width:130,height:130});
+ lowselector_2input.setId("lowselector_2input");
+ lowselector_2input.setResizeable(false);
+
+// var FTPort_hartTransPlus = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+// FTPort_hartTransPlus.setName("FTPort_hartTransplus");
+// FTPort_hartTransPlus.setId("FTPort_hartTransplusId");
+//
+//
+// var FTPort_hartTransMinu = hartTrans_FT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+// FTPort_hartTransMinu.setName("FTPort_hartTransminus");
+// FTPort_hartTransMinu.setId("FTPort_hartTransminusId");
+
+
+
+
+ canvas.add( lowselector_2input, x1,y1);
+ return lowselector_2input;
+
+ }
+
+
+ var LabeldLowSelectorFigure_2Input = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, 7, "Low Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // low symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 100 23 l -12 8 l 12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 65 l 30 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 75, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ this.canvas.paper.path("M 60 130 l 0 -38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 70, 120, "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+
+
+ // Low selector with 3 inputs
+
+
+ function LowSelector_3_Input(canvas,x1,y1){
+
+ var lowselector_3input = new LabeldLowSelectorFigure_3Input({width:130,height:130});
+ lowselector_3input.setId("lowselector_3input");
+ lowselector_3input.setResizeable(false);
+
+
+
+ canvas.add( lowselector_3input, x1,y1);
+ return lowselector_3input;
+
+ }
+
+
+ var LabeldLowSelectorFigure_3Input = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, -10, "Low Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // low symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 100 23 l -12 8 l 12 8").
+ attr({"stroke-width" : 2
+ });
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 65 l 30 0").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 75, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // b input
+ this.canvas.paper.path("M 60 130 l 0 -38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 70, 120, "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // c input
+ this.canvas.paper.path("M 60 0 l 0 38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 50, 10, "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+
+
+ // Low selector with 4 inputs
+
+
+ function LowSelector_4_Input(canvas,x1,y1){
+
+ var lowselector_4input = new LabeldLowSelectorFigure_4Input({width:130,height:130});
+ lowselector_4input.setId("lowselector_4input");
+ lowselector_4input.setResizeable(false);
+
+
+
+ canvas.add( lowselector_4input, x1,y1);
+ return lowselector_4input;
+
+ }
+
+
+ var LabeldLowSelectorFigure_4Input = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 130, 130).attr({
+ "stroke-width" : 0
+ });
+ this.canvas.paper.text( 60, -10, "Low Selector").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(60, 65, 30).
+ attr({"stroke-width" : 1
+ });
+
+ // low symbol in rect
+ this.canvas.paper.rect(82, 18, 25, 25).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 100 23 l -12 8 l 12 8").
+ attr({"stroke-width" : 2
+ });
+
+
+ // out
+ this.canvas.paper.path("M 90 65 l 40 0").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 105, 80, "Out").attr({
+ 'stroke' : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+
+ // a input
+ this.canvas.paper.path("M 0 35 l 33 18").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 10, 53, "a").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+
+ // d input
+ this.canvas.paper.path("M 0 110 l 38 -28").attr({
+ "stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 18, 110, "d").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ // b input
+ this.canvas.paper.path("M 60 130 l 0 -38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 70, 120, "b").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ // c input
+ this.canvas.paper.path("M 60 0 l 0 38").
+ attr({"stroke-width" : 2,
+ "stroke-dasharray" : "-",
+ "arrow-end": "open-narrow-short"
+ });
+ this.canvas.paper.text( 50, 10, "c").attr({
+ 'stroke' : 'black',
+ 'font-size' : 20,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/symbols/P2ESymbols.js b/experiment/simulation/js/H2L_src/symbols/P2ESymbols.js
new file mode 100644
index 0000000..57d440a
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/P2ESymbols.js
@@ -0,0 +1,472 @@
+
+
+
+// P2E LY symbol
+
+ function P2E_LY_100(canvas,x1,y1){
+
+ var LY100_p2e = new LabeldFigure_P2E_LY100({width:130,height:100});
+ LY100_p2e.setId("LY100_p2e");
+ LY100_p2e.setResizeable(false);
+
+ var LY100Port_p2ePlus = LY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,35));
+ LY100Port_p2ePlus.setName("LY100_p2ePlus");
+ LY100Port_p2ePlus.setId("LY100_p2ePlusId");
+
+
+ var LY100Port_p2eMinus = LY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,75));
+ LY100Port_p2eMinus.setName("LY100_p2eMinus");
+ LY100Port_p2eMinus.setId("LY100_p2eMinusId");
+
+ var LY100Port_p2e = LY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,54));
+ LY100Port_p2e.setName("LY100_p2e");
+ LY100Port_p2e.setId("LY100_p2eId");
+
+ canvas.add( LY100_p2e, x1,y1);
+ return LY100_p2e;
+
+ }
+
+
+ var LabeldFigure_P2E_LY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 130, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(62, 55, 23).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 62, 55, "LY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 0 55 l 40 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 35 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 15, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 100 35 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 110 25 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 100 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 65, 5, "P/E Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+ // P2E TY symbol
+
+ function P2E_TY_100(canvas,x1,y1){
+
+ var TY100_p2e = new LabeldFigure_P2E_TY100({width:130,height:100});
+ TY100_p2e.setId("TY100_p2e");
+ TY100_p2e.setResizeable(false);
+
+ var TY100Port_p2ePlus = TY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,35));
+ TY100Port_p2ePlus.setName("TY100_p2ePlus");
+ TY100Port_p2ePlus.setId("TY100_p2ePlusId");
+
+
+ var TY100Port_p2eMinus = TY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,75));
+ TY100Port_p2eMinus.setName("TY100_p2eMinus");
+ TY100Port_p2eMinus.setId("TY100_p2eMinusId");
+
+ var TY100Port_p2e = TY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,54));
+ TY100Port_p2e.setName("TY100_p2e");
+ TY100Port_p2e.setId("TY100_p2eId");
+
+ canvas.add( TY100_p2e, x1,y1);
+ return TY100_p2e;
+
+ }
+
+
+ var LabeldFigure_P2E_TY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 130, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(62, 55, 23).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 62, 55, "TY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 0 55 l 40 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 35 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 15, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 100 35 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 110 25 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 100 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 65, 5, "P/E Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+ // P2E PY symbol
+
+ function P2E_PY_100(canvas,x1,y1){
+
+ var PY100_p2e = new LabeldFigure_P2E_PY100({width:130,height:100});
+ PY100_p2e.setId("PY100_p2e");
+ PY100_p2e.setResizeable(false);
+
+ var PY100Port_p2ePlus = PY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,35));
+ PY100Port_p2ePlus.setName("PY100_p2ePlus");
+ PY100Port_p2ePlus.setId("PY100_p2ePlusId");
+
+
+ var PY100Port_p2eMinus = PY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,75));
+ PY100Port_p2eMinus.setName("PY100_p2eMinus");
+ PY100Port_p2eMinus.setId("PY100_p2eMinusId");
+
+ var PY100Port_p2e = PY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,54));
+ PY100Port_p2e.setName("PY100_p2e");
+ PY100Port_p2e.setId("PY100_p2eId");
+
+ canvas.add( PY100_p2e, x1,y1);
+ return PY100_p2e;
+
+ }
+
+
+ var LabeldFigure_P2E_PY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 130, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(62, 55, 23).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 62, 55, "PY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 0 55 l 40 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 35 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 15, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 100 35 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 110 25 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 100 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 65, 5, "P/E Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+ // P2E FY symbol
+
+ function P2E_FY_100(canvas,x1,y1){
+
+ var FY100_p2e = new LabeldFigure_P2E_FY100({width:130,height:100});
+ FY100_p2e.setId("FY100_p2e");
+ FY100_p2e.setResizeable(false);
+
+ var FY100Port_p2ePlus = FY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,35));
+ FY100Port_p2ePlus.setName("FY100_p2ePlus");
+ FY100Port_p2ePlus.setId("FY100_p2ePlusId");
+
+
+ var FY100Port_p2eMinus = FY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,75));
+ FY100Port_p2eMinus.setName("FY100_p2eMinus");
+ FY100Port_p2eMinus.setId("FY100_p2eMinusId");
+
+ var FY100Port_p2e = FY100_p2e.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,54));
+ FY100Port_p2e.setName("FY100_p2e");
+ FY100Port_p2e.setId("FY100_p2eId");
+
+ canvas.add( FY100_p2e, x1,y1);
+ return FY100_p2e;
+
+ }
+
+
+ var LabeldFigure_P2E_FY100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 130, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(62, 55, 23).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 62, 55, "FY 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 0 55 l 40 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 35 47 l -15 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 15, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 100 35 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 110 25 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(85, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 100 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 65, 5, "P/E Converter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+
+
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/symbols/PTSymbols.js b/experiment/simulation/js/H2L_src/symbols/PTSymbols.js
new file mode 100644
index 0000000..06d495c
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/PTSymbols.js
@@ -0,0 +1,619 @@
+
+
+
+
+// 2 Wire Trasmitter
+
+ function TwoWireTransmitter_PT(canvas,x1,y1){
+
+ var twoWireTrans_PT = new LabeldTwoWireTrnsmtrFigure_PT({width:100,height:95});
+ twoWireTrans_PT.setId("twoWireTrans_PT");
+ twoWireTrans_PT.setResizeable(false);
+
+ var PTPort_twoWireTransPlus = twoWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ PTPort_twoWireTransPlus.setName("PT_twowireTransPlus");
+ PTPort_twoWireTransPlus.setId("PT_twowireTransPlusId");
+
+ var PTPort_twoWireTransMinus = twoWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ PTPort_twoWireTransMinus.setName("PT_twowireTransMinus");
+ PTPort_twoWireTransMinus.setId("PT_twowireTransMinusId");
+
+
+ canvas.add( twoWireTrans_PT, x1,y1);
+ return twoWireTrans_PT;
+
+ }
+
+
+ var LabeldTwoWireTrnsmtrFigure_PT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "PT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "2-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// 3 wire transmitter
+
+ function ThreeWireTransmitter_PT(canvas,x1,y1){
+
+ var threeWireTrans_PT = new LabeldThreeWireTrnsmtrFigure_PT({width:120,height:100});
+ threeWireTrans_PT.setId("threeWireTrans_PT");
+ threeWireTrans_PT.setResizeable(false);
+
+ var PTPort_threeWireTransSuplyPlus = threeWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ PTPort_threeWireTransSuplyPlus.setName("PT_threeWireTransSuplyPlus");
+ PTPort_threeWireTransSuplyPlus.setId("PT_threeWireTransSuplyPlusId");
+
+ var PTPort_threeWireTransSigPlus = threeWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ PTPort_threeWireTransSigPlus.setName("PT_threeWireTransSigPlus");
+ PTPort_threeWireTransSigPlus.setId("PT_threeWireTransSigPlusId");
+
+ var PTPort_threeWireTransMinus = threeWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,100));
+ PTPort_threeWireTransMinus.setName("PT_threeWireTransMinus");
+ PTPort_threeWireTransMinus.setId("PT_threeWireTransMinusId");
+
+
+ canvas.add( threeWireTrans_PT, x1,y1);
+ return threeWireTrans_PT;
+
+ }
+
+
+ var LabeldThreeWireTrnsmtrFigure_PT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 120, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(60, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 60, 40, "PT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 100, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 105, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(0, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(40, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 50 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(80, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 90 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 100 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 60, 5, "3-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+// 4 wire transmitter
+
+
+function FourWireTransmitter_PT(canvas,x1,y1){
+
+ var fourWireTrans_PT = new LabeldFourWireTrnsmtrFigure_PT({width:110,height:130});
+ fourWireTrans_PT.setId("fourWireTrans_PT");
+ fourWireTrans_PT.setResizeable(false);
+
+ var PTPort_fourWireTransSuplyPlus = fourWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,60));
+ PTPort_fourWireTransSuplyPlus.setName("PT_fourWireTransSuplyPlus");
+ PTPort_fourWireTransSuplyPlus.setId("PT_fourWireTransSuplyPlusId");
+
+
+ var PTPort_fourWireTransSuplyMinus = fourWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,90));
+ PTPort_fourWireTransSuplyMinus.setName("PT_fourWireTransSuplyMinus");
+ PTPort_fourWireTransSuplyMinus.setId("PT_fourWireTransSuplyMinusId");
+
+ var PTPort_fourWireTransSigPlus = fourWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,60));
+ PTPort_fourWireTransSigPlus.setName("PT_fourWireTransSigPlus");
+ PTPort_fourWireTransSigPlus.setId("PT_fourWireTransSigPlusId");
+
+ var PTPort_fourWireTransSigMinus = fourWireTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,90));
+ PTPort_fourWireTransSigMinus.setName("PT_fourWireTransSigMinus");
+ PTPort_fourWireTransSigMinus.setId("PT_fourWireTransSigMinusId");
+
+
+ canvas.add( fourWireTrans_PT, x1,y1);
+ return fourWireTrans_PT;
+
+ }
+
+
+ var LabeldFourWireTrnsmtrFigure_PT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 110, 130).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.circle(55, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 55, 40, "PT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.text( 95, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 95, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.rect(0, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(0, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 10 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 80 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 90 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 80 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+
+ this.canvas.paper.text( 55, 10, "4-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// PT HART TRANSMITTER
+
+
+function HartTransmitter_PT(canvas,x1,y1){
+
+ var hartTrans_PT = new LabeldHartTrnsmtrFigure_PT({width:100,height:105});
+ hartTrans_PT.setId("hartTrans_PT");
+ hartTrans_PT.setResizeable(false);
+
+ var PTPort_hartTransPlus = hartTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+ PTPort_hartTransPlus.setName("PTPort_hartTransplus");
+ PTPort_hartTransPlus.setId("PTPort_hartTransplusId");
+
+
+ var PTPort_hartTransMinu = hartTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+ PTPort_hartTransMinu.setName("PTPort_hartTransminus");
+ PTPort_hartTransMinu.setId("PTPort_hartTransminusId");
+
+
+
+
+ canvas.add( hartTrans_PT, x1,y1);
+ return hartTrans_PT;
+
+ }
+
+
+ var LabeldHartTrnsmtrFigure_PT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 100, 105).
+ attr({"stroke-width" : 0
+ });
+ this.canvas.paper.text( 50, 10, "HART Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(50, 65, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 40, "PT").attr({
+ stroke : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 12 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 58 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 72 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 50, 60, "Signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+ this.canvas.paper.text( 50, 72, "4-20mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 70, 40, 40);
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// FFT Trasmitter
+
+ function FFT_Transmitter_PT(canvas,x1,y1){
+
+ var ffTrans_PT = new LabeldFFT_TrnsmtrFigure_PT({width:100,height:100});
+ ffTrans_PT.setId("ffTrans_PT");
+ ffTrans_PT.setResizeable(false);
+
+ var PTPort_ffTransPlus = ffTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(25,0));
+ PTPort_ffTransPlus.setName("PT_ffTransPlus");
+ PTPort_ffTransPlus.setId("PT_ffTransPlusId");
+
+
+ var PTPort_ffTransMinus = ffTrans_PT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(70,0));
+ PTPort_ffTransMinus.setName("PT_ffTransMinus");
+ PTPort_ffTransMinus.setId("PT_ffTransMinusId");
+
+
+ canvas.add( ffTrans_PT, x1,y1);
+ return ffTrans_PT;
+
+ }
+
+
+ var LabeldFFT_TrnsmtrFigure_PT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 0
+ });
+
+
+
+ this.canvas.paper.rect(5, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 10 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.circle(50, 65, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 55, "PT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 52, 40, 40);
+ this.canvas.paper.text( 50, 98, "Foundation Field Bus ").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 110, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/experiment/simulation/js/H2L_src/symbols/PneumaticTransSymbols.js b/experiment/simulation/js/H2L_src/symbols/PneumaticTransSymbols.js
new file mode 100644
index 0000000..a7fd017
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/PneumaticTransSymbols.js
@@ -0,0 +1,386 @@
+
+
+
+// Pneumatic transmitter LT 100 symbol
+
+ function PT_LT_100(canvas,x1,y1){
+
+ var PT_LT100 = new LabeldFigure_PT_LT100({width:100,height:130});
+ PT_LT100.setId("PT_LT100");
+ PT_LT100.setResizeable(false);
+
+ var LT100Port_PT = PT_LT100.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,103));
+ LT100Port_PT.setName("LT100_PT");
+ LT100Port_PT.setId("LT100_PTID");
+
+
+ canvas.add( PT_LT100, x1,y1);
+ return PT_LT100;
+
+ }
+
+
+ var LabeldFigure_PT_LT100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 130).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 60, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 60, "LT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ this.canvas.paper.path("M 50 85 l 0 47 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 60 92 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 60 102 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 10, "Pneumatic").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 25, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 13,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+ // Pneumatic transmitter TT 100 symbol
+
+ function PT_TT_100(canvas,x1,y1){
+
+ var PT_TT100 = new LabeldFigure_PT_TT100({width:100,height:130});
+ PT_TT100.setId("PT_TT100");
+ PT_TT100.setResizeable(false);
+
+ var TT100Port_PT = PT_TT100.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,103));
+ TT100Port_PT.setName("TT100_PT");
+ TT100Port_PT.setId("TT100_PTID");
+
+
+ canvas.add( PT_TT100, x1,y1);
+ return PT_TT100;
+
+ }
+
+ var LabeldFigure_PT_TT100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 130).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 60, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 60, "TT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ this.canvas.paper.path("M 50 85 l 0 47 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 60 92 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 60 102 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 10, "Pneumatic").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 25, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 13,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+ // Pneumatic transmitter PT 100 symbol
+
+ function PT_PT_100(canvas,x1,y1){
+
+ var PT_PT100 = new LabeldFigure_PT_PT100({width:100,height:130});
+ PT_PT100.setId("PT_PT100");
+ PT_PT100.setResizeable(false);
+
+ var PT100Port_PT = PT_PT100.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,103));
+ PT100Port_PT.setName("PT100_PT");
+ PT100Port_PT.setId("PT100_PTID");
+
+
+ canvas.add( PT_PT100, x1,y1);
+ return PT_PT100;
+
+ }
+
+
+ var LabeldFigure_PT_PT100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 130).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 60, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 60, "PT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ this.canvas.paper.path("M 50 85 l 0 47 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 60 92 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 60 102 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 10, "Pneumatic").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 25, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 13,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
+ // Pneumatic transmitter FT 100 symbol
+
+ function PT_FT_100(canvas,x1,y1){
+
+ var PT_FT100 = new LabeldFigure_PT_FT100({width:100,height:130});
+ PT_FT100.setId("PT_FT100");
+ PT_FT100.setResizeable(false);
+
+ var FT100Port_PT = PT_FT100.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,103));
+ FT100Port_PT.setName("FT100_PT");
+ FT100Port_PT.setId("FT100_PTID");
+
+
+ canvas.add( PT_FT100, x1,y1);
+ return PT_FT100;
+
+ }
+
+
+ var LabeldFigure_PT_FT100 = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 130).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 60, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 60, "FT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ this.canvas.paper.path("M 50 85 l 0 47 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 60 92 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 60 102 l -20 20 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 10, "Pneumatic").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 25, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 13,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+ });
+
+
\ No newline at end of file
diff --git a/experiment/simulation/js/H2L_src/symbols/TTSymbols.js b/experiment/simulation/js/H2L_src/symbols/TTSymbols.js
new file mode 100644
index 0000000..07b3715
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/TTSymbols.js
@@ -0,0 +1,614 @@
+
+
+
+
+// 2 Wire Trasmitter
+
+ function TwoWireTransmitter_TT(canvas,x1,y1){
+
+ var twoWireTrans_TT = new LabeldTwoWireTrnsmtrFigure_TT({width:100,height:95});
+ twoWireTrans_TT.setId("twoWireTrans_TT");
+ twoWireTrans_TT.setResizeable(false);
+
+ var TTPort_twoWireTransPlus = twoWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ TTPort_twoWireTransPlus.setName("TT_twowireTransPlus");
+ TTPort_twoWireTransPlus.setId("TT_twowireTransPlusId");
+
+ var TTPort_twoWireTransMinus = twoWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ TTPort_twoWireTransMinus.setName("TT_twowireTransMinus");
+ TTPort_twoWireTransMinus.setId("TT_twowireTransMinusId");
+
+
+ canvas.add( twoWireTrans_TT, x1,y1);
+ return twoWireTrans_TT;
+
+ }
+
+
+ var LabeldTwoWireTrnsmtrFigure_TT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 95).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(50, 35, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 35, "TT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(5, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 65 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 55, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 75 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+ this.canvas.paper.text( 50, 5, "2-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// 3 wire transmitter
+
+ function ThreeWireTransmitter_TT(canvas,x1,y1){
+
+ var threeWireTrans_TT = new LabeldThreeWireTrnsmtrFigure_TT({width:120,height:100});
+ threeWireTrans_TT.setId("threeWireTrans_TT");
+ threeWireTrans_TT.setResizeable(false);
+
+ var TTPort_threeWireTransSuplyPlus = threeWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,78));
+ TTPort_threeWireTransSuplyPlus.setName("TT_threeWireTransSuplyPlus");
+ TTPort_threeWireTransSuplyPlus.setId("TT_threeWireTransSuplyPlusId");
+
+ var TTPort_threeWireTransSigPlus = threeWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,78));
+ TTPort_threeWireTransSigPlus.setName("TT_threeWireTransSigPlus");
+ TTPort_threeWireTransSigPlus.setId("TT_threeWireTransSigPlusId");
+
+ var TTPort_threeWireTransMinus = threeWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(50,100));
+ TTPort_threeWireTransMinus.setName("TT_threeWireTransMinus");
+ TTPort_threeWireTransMinus.setId("TT_threeWireTransMinusId");
+
+
+ canvas.add( threeWireTrans_TT, x1,y1);
+ return threeWireTrans_TT;
+
+ }
+
+
+ var LabeldThreeWireTrnsmtrFigure_TT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 120, 100).
+ attr({"stroke-width" : 0
+ });
+
+ this.canvas.paper.circle(60, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 60, 40, "TT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 100, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 105, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(0, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(40, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 50 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(80, 60, 40, 40).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 90 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 100 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 60, 5, "3-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+// 4 wire transmitter
+
+
+function FourWireTransmitter_TT(canvas,x1,y1){
+
+ var fourWireTrans_TT = new LabeldFourWireTrnsmtrFigure_TT({width:110,height:130});
+ fourWireTrans_TT.setId("fourWireTrans_TT");
+ fourWireTrans_TT.setResizeable(false);
+
+ var TTPort_fourWireTransSuplyPlus = fourWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,60));
+ TTPort_fourWireTransSuplyPlus.setName("TT_fourWireTransSuplyPlus");
+ TTPort_fourWireTransSuplyPlus.setId("TT_fourWireTransSuplyPlusId");
+
+
+ var TTPort_fourWireTransSuplyMinus = fourWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,90));
+ TTPort_fourWireTransSuplyMinus.setName("TT_fourWireTransSuplyMinus");
+ TTPort_fourWireTransSuplyMinus.setId("TT_fourWireTransSuplyMinusId");
+
+ var TTPort_fourWireTransSigPlus = fourWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,60));
+ TTPort_fourWireTransSigPlus.setName("TT_fourWireTransSigPlus");
+ TTPort_fourWireTransSigPlus.setId("TT_fourWireTransSigPlusId");
+
+ var TTPort_fourWireTransSigMinus = fourWireTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(100,90));
+ TTPort_fourWireTransSigMinus.setName("TT_fourWireTransSigMinus");
+ TTPort_fourWireTransSigMinus.setId("TT_fourWireTransSigMinusId");
+
+
+ canvas.add( fourWireTrans_TT, x1,y1);
+ return fourWireTrans_TT;
+
+ }
+
+
+ var LabeldFourWireTrnsmtrFigure_TT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 110, 130).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.circle(55, 40, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 55, 40, "TT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 30, "supply").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 15, 45, "24 VDC").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.text( 95, 30, "signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 95, 45, "4-20 mA").attr({
+ stroke : 'black',
+ 'font-size' : 7,
+ "font-family": "sans-serif"
+ });
+
+
+ this.canvas.paper.rect(0, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 10 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(0, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 10 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 60, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+
+ this.canvas.paper.path("M 80 80 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 90 70 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 95, 40, 35).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 80 115 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+
+
+ this.canvas.paper.text( 55, 10, "4-Wire Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+// TT HART TRANSMITTER
+
+
+function HartTransmitter_TT(canvas,x1,y1){
+
+ var hartTrans_TT = new LabeldHartTrnsmtrFigure_TT({width:100,height:105});
+ hartTrans_TT.setId("hartTrans_TT");
+ hartTrans_TT.setResizeable(false);
+
+ var TTPort_hartTransPlus = hartTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(5,60));
+ TTPort_hartTransPlus.setName("TTPort_hartTransplus");
+ TTPort_hartTransPlus.setId("TTPort_hartTransplusId");
+
+
+ var TTPort_hartTransMinu = hartTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(95,60));
+ TTPort_hartTransMinu.setName("TTPort_hartTransminus");
+ TTPort_hartTransMinu.setId("TTPort_hartTransminusId");
+
+
+
+
+ canvas.add( hartTrans_TT, x1,y1);
+ return hartTrans_TT;
+
+ }
+
+
+ var LabeldHartTrnsmtrFigure_TT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 100, 105).
+ attr({"stroke-width" : 0
+ });
+ this.canvas.paper.text( 50, 10, "HART Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.circle(50, 65, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 40, "TT").attr({
+ stroke : 'black',
+ 'font-size' : 15,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.path("M 12 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 20 58 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 72 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 50, 60, "Signal").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+ this.canvas.paper.text( 50, 72, "4-20mA").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 70, 40, 40);
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+// FFT Trasmitter
+
+ function FFT_Transmitter_TT(canvas,x1,y1){
+
+ var ffTrans_TT = new LabeldFFT_TrnsmtrFigure_TT({width:100,height:100});
+ ffTrans_TT.setId("ffTrans_TT");
+ ffTrans_TT.setResizeable(false);
+
+ var TTPort_ffTransPlus = ffTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(25,0));
+ TTPort_ffTransPlus.setName("TT_ffTransPlus");
+ TTPort_ffTransPlus.setId("TT_ffTransPlusId");
+
+
+ var TTPort_ffTransMinus = ffTrans_TT.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(70,0));
+ TTPort_ffTransMinus.setName("TT_ffTransMinus");
+ TTPort_ffTransMinus.setId("TT_ffTransMinusId");
+
+
+ canvas.add( ffTrans_TT, x1,y1);
+ return ffTrans_TT;
+
+ }
+
+
+ var LabeldFFT_TrnsmtrFigure_TT = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 0
+ });
+
+
+
+ this.canvas.paper.rect(5, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 15 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 25 10 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(50, 0, 45, 40).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 60 20 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.circle(50, 65, 25).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 55, "TT 100").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.image("images/singwave.png",30, 52, 40, 40);
+
+ this.canvas.paper.text( 50, 98, "Foundation Field Bus ").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 50, 110, "Transmitter").attr({
+ stroke : 'black',
+ 'font-size' : 10,
+ "font-family": "sans-serif"
+ });
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+
+
diff --git a/experiment/simulation/js/H2L_src/symbols/commonSymbols.js b/experiment/simulation/js/H2L_src/symbols/commonSymbols.js
new file mode 100644
index 0000000..3a0880e
--- /dev/null
+++ b/experiment/simulation/js/H2L_src/symbols/commonSymbols.js
@@ -0,0 +1,505 @@
+
+// Power Supply Symbol
+
+ function powerSupply(canvas,x1,y1){
+ var pwrsply = new LabeldpowerSupplyFigure({width:100,height:100});
+ pwrsply.setId("PowerSupply");
+ pwrsply.setResizeable(false);
+
+ var Port_pwrsplyPlus = pwrsply.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,35));
+ Port_pwrsplyPlus.setName("psPlus");
+ Port_pwrsplyPlus.setId("psPlusId");
+
+ var Port_pwrsplyMinus = pwrsply.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(102,65));
+ Port_pwrsplyMinus.setName("psMinus");
+ Port_pwrsplyMinus.setId("psMinusId");
+
+
+ canvas.add( pwrsply, x1,y1);
+ return pwrsply;
+
+}
+
+
+var LabeldpowerSupplyFigure = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.rect(70, 20, 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 79 35 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 86 28 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(70, 50, 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 79 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 48, 40, "Power").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 48, 55, "Supply").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+// Analog Controller IN / Signal
+
+ function signal(canvas,x2,y2){
+ var signal = new LabeldSignalFigure({width:100,height:100});
+ // signal.setStroke(0);
+ // signal.setBackgroundColor("#ffffff");
+ signal.setResizeable(false);
+ signal.setId("Signal");
+
+ var port_sgnlMinus = signal.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,65));
+ port_sgnlMinus.setName("sgnlMinus");
+ port_sgnlMinus.setId("sgnlMinusId");
+
+ var port_sgnlplus = signal.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,35));
+ port_sgnlplus.setName("sgnlplus");
+ port_sgnlplus.setId("sgnlplusId");
+
+ /* rec.port1 = rec.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(70,0));
+ */
+
+
+ //rec1.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
+ // rec2.installEditPolicy(new draw2d.policy.figure.AntSelectionFeedbackPolicy());
+ // rec2.installEditPolicy(new draw2d.policy.figure.SlimSelectionFeedbackPolicy());
+
+
+ canvas.add( signal, x2,y2);
+ return signal;
+
+}
+
+
+
+
+ var LabeldSignalFigure = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ // this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.rect(0, 20, 30, 30).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 8 35 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 16 28 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(0, 50, 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 9 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 70, 40, "Analog").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 68, 55, "IN").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+ // CONFIGURATOR
+
+function Configurator(canvas,x1,y1){
+
+ var configurator = new LabeldConfiguratorFigure({width:100,height:100});
+ configurator.setId("fourWireTrans_LT");
+ configurator.setResizeable(false);
+
+
+ var configuratorPlus = configurator.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(18,100));
+ configuratorPlus.setName("configuratorPlus");
+ configuratorPlus.setId("configuratorPlusId");
+
+ var configuratorMinu = configurator.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(80,100));
+ configuratorMinu.setName("configuratorMinu");
+ configuratorMinu.setId("configuratorMinuId");
+
+
+
+
+ canvas.add( configurator, x1,y1);
+ return configurator;
+
+ }
+
+
+ var LabeldConfiguratorFigure = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ //this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+ /* this.canvas.paper.path("M 15 0 l -15 30 l 30 0 l -15 -30").
+ attr({"stroke-width" : 1
+ }); */
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.text( 50, 10, "Configurator").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.rect(10, 35, 20, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.rect(40, 35, 20, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.rect(70, 35, 20, 20).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 8 88 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 18 78 l 0 20 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 70 88 l 20 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+ // Analog Controller IN / Signal
+
+ function fftCard(canvas,x2,y2){
+ var fft_card = new LabeldFFT_CardFigure({width:100,height:100});
+ // signal.setStroke(0);
+ // signal.setBackgroundColor("#ffffff");
+ fft_card.setResizeable(false);
+ fft_card.setId("fft_card");
+
+ var port_fftCardPlus = fft_card.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,10));
+ port_fftCardPlus.setName("fftCardPlus");
+ port_fftCardPlus.setId("fftCardPlusId");
+
+ var port_fftCardMinus = fft_card.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,90));
+ port_fftCardMinus.setName("fftCardMinus");
+ port_fftCardMinus.setId("fftCardMinusId");
+
+ /* rec.port1 = rec.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(70,0));
+ */
+
+
+ //rec1.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
+ // rec2.installEditPolicy(new draw2d.policy.figure.AntSelectionFeedbackPolicy());
+ // rec2.installEditPolicy(new draw2d.policy.figure.SlimSelectionFeedbackPolicy());
+
+
+ canvas.add( fft_card, x2,y2);
+ return fft_card;
+
+}
+
+
+
+
+ var LabeldFFT_CardFigure = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ // this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 0
+ });
+ this.canvas.paper.rect(40, 0, 60, 100).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.rect(40, 0, 60, 100).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 0 10 l 40 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 0 90 l 40 0 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 45 10 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 53 3 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 45 90 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+ this.canvas.paper.path("M 25 10 l 0 15 l -10 5 l 20 5 l -20 5 l 20 5 l -20 5 l 20 5 l -20 5 l 20 5 l -20 5 l 10 5 l 0 15").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 0, 50, "250").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 0, 60, "ohm").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+ this.canvas.paper.text( 70, 40, "FFT").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+ this.canvas.paper.text( 70, 60, "Card").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
+
+
+
+ // Analog OUT
+
+ function AnalogOut(canvas,x2,y2){
+// var signal = new LabeldSignalFigure({width:100,height:100});
+ var analogOut = new LabeldAnalogOutFigure({width:100,height:100});
+ // analogOut.setStroke(0);
+ // analogOut.setBackgroundColor("#ffffff");
+ analogOut.setResizeable(false);
+ analogOut.setId("AnalogOut");
+
+ var port_analogOutMinus = analogOut.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,65));
+ port_analogOutMinus.setName("analogOutMinus");
+ port_analogOutMinus.setId("analogOutMinusId");
+
+ var port_analogOutplus = analogOut.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(0,35));
+ port_analogOutplus.setName("analogOutplus");
+ port_analogOutplus.setId("analogOutplusId");
+
+ /* rec.port1 = rec.createPort("hybrid", new draw2d.layout.locator.XYRelPortLocator(70,0));
+ */
+
+
+ //rec1.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
+ // rec2.installEditPolicy(new draw2d.policy.figure.AntSelectionFeedbackPolicy());
+ // rec2.installEditPolicy(new draw2d.policy.figure.SlimSelectionFeedbackPolicy());
+
+
+ canvas.add( analogOut, x2,y2);
+ return analogOut;
+
+}
+
+
+ var LabeldAnalogOutFigure = draw2d.SetFigure.extend({
+
+ init : function(attr)
+ {
+ this._super(attr);
+
+ this.strokeScale = true; // scale the stroke width of the children nodes if the parent resize. available with version 5.1.0 of draw2d
+ this.setKeepAspectRatio(false);
+ // this.installEditPolicy(new SelectionMenuPolicy());
+ },
+
+ createSet : function()
+ {
+ this.canvas.paper.setStart();
+
+
+ /* this.canvas.paper.text(0, 6, 'header').attr({"text-anchor":"start"}); */
+ /* this.canvas.paper.image('https://png.icons8.com/metro/1600/online.png',x,16,40, 40); */
+
+
+ // var x = ((this.width-20)/2);
+
+
+ this.canvas.paper.rect(0, 0, 100, 100).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.rect(0, 20, 30, 30).
+ attr({"stroke-width" : 1
+ });
+ this.canvas.paper.path("M 8 35 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.path("M 16 28 l 0 15 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.rect(0, 50, 30, 30).
+ attr({"stroke-width" : 1
+ });
+
+ this.canvas.paper.path("M 9 65 l 15 0 ").
+ attr({"stroke-width" : 2
+ });
+
+ this.canvas.paper.text( 70, 40, "Analog").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+ this.canvas.paper.text( 68, 55, "OUT").attr({
+ stroke : 'black',
+ 'font-size' : 12,
+ "font-family": "sans-serif"
+ });
+
+
+
+ return this.canvas.paper.setFinish();
+ },
+
+
+});
+
\ No newline at end of file
diff --git a/experiment/simulation/js/README.md b/experiment/simulation/js/README.md
deleted file mode 100644
index b6e0cff..0000000
--- a/experiment/simulation/js/README.md
+++ /dev/null
@@ -1 +0,0 @@
-### This folder contains all the js files used in the simulation.
\ No newline at end of file
diff --git a/experiment/simulation/js/dist/draw2d.js b/experiment/simulation/js/dist/draw2d.js
new file mode 100644
index 0000000..f2c59b6
--- /dev/null
+++ b/experiment/simulation/js/dist/draw2d.js
@@ -0,0 +1,63965 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["draw2d"] = factory();
+ else
+ root["draw2d"] = factory();
+})(window, function() {
+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 = "./src/index.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./node_modules/canvg-browser/index.js":
+/*!*********************************************!*\
+ !*** ./node_modules/canvg-browser/index.js ***!
+ \*********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+ var RGBColor = __webpack_require__(/*! rgbcolor */ "./node_modules/rgbcolor/index.js");
+ var stackblur = __webpack_require__(/*! stackblur */ "./node_modules/stackblur/index.js");
+ var xmldom = __webpack_require__(/*! xmldom */ "./node_modules/xmldom/dom-parser.js");
+
+/*
+ * canvg.js - Javascript SVG parser and renderer on Canvas
+ * MIT Licensed
+ * Gabe Lerner (gabelerner@gmail.com)
+ * http://code.google.com/p/canvg/
+ *
+ * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
+ */
+
+/*
+canvg(target, s)
+ empty parameters: replace all 'svg' elements on page with 'canvas' elements
+ target: canvas element or the id of a canvas element
+ s: svg string, url to svg file, or xml document
+ opts: optional hash of options
+ ignoreMouse: true => ignore mouse events
+ ignoreAnimation: true => ignore animations
+ ignoreDimensions: true => does not try to resize canvas
+ ignoreClear: true => does not clear canvas
+ offsetX: int => draws at a x offset
+ offsetY: int => draws at a y offset
+ scaleWidth: int => scales horizontally to width
+ scaleHeight: int => scales vertically to height
+ renderCallback: function => will call the function after the first render is completed
+ forceRedraw: function => will call the function on every frame, if it returns true, will redraw
+*/
+function canvg(target, s, opts) {
+
+ // no parameters
+ if (target == null && s == null && opts == null) {
+ var svgTags = document.querySelectorAll('svg');
+ for (var i=0; i
~\.\[:]+)/g;
+ var classRegex = /(\.[^\s\+>~\.\[:]+)/g;
+ var pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi;
+ var pseudoClassWithBracketsRegex = /(:[\w-]+\([^\)]*\))/gi;
+ var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g;
+ var elementRegex = /([^\s\+>~\.\[:]+)/g;
+
+ var findMatch = function(regex, type) {
+ var matches = selector.match(regex);
+ if (matches == null) {
+ return;
+ }
+ typeCount[type] += matches.length;
+ selector = selector.replace(regex, ' ');
+ };
+
+ selector = selector.replace(/:not\(([^\)]*)\)/g, ' $1 ');
+ selector = selector.replace(/{[^]*/gm, ' ');
+ findMatch(attributeRegex, 1);
+ findMatch(idRegex, 0);
+ findMatch(classRegex, 1);
+ findMatch(pseudoElementRegex, 2);
+ findMatch(pseudoClassWithBracketsRegex, 1);
+ findMatch(pseudoClassRegex, 1);
+ selector = selector.replace(/[\*\s\+>~]/g, ' ');
+ selector = selector.replace(/[#\.]/g, ' ');
+ findMatch(elementRegex, 2);
+ return typeCount.join('');
+}
+
+function build(opts) {
+ var svg = { opts: opts };
+
+ var matchesSelector = getMatchesSelector();
+
+ if (typeof CanvasRenderingContext2D != 'undefined') {
+ CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh, opts) {
+ var cOpts = {
+ ignoreMouse: true,
+ ignoreAnimation: true,
+ ignoreDimensions: true,
+ ignoreClear: true,
+ offsetX: dx,
+ offsetY: dy,
+ scaleWidth: dw,
+ scaleHeight: dh
+ };
+
+ for(var prop in opts) {
+ if(opts.hasOwnProperty(prop)){
+ cOpts[prop] = opts[prop];
+ }
+ }
+ canvg(this.canvas, s, cOpts);
+ };
+ }
+
+ svg.FRAMERATE = 30;
+ svg.MAX_VIRTUAL_PIXELS = 30000;
+
+ svg.log = function(msg) {};
+ if (svg.opts.log == true && typeof console != 'undefined') {
+ svg.log = function(msg) { console.log(msg); };
+ }
+
+ // globals
+ svg.init = function(ctx) {
+ var uniqueId = 0;
+ svg.UniqueId = function () { uniqueId++; return 'canvg' + uniqueId; };
+ svg.Definitions = {};
+ svg.Styles = {};
+ svg.StylesSpecificity = {};
+ svg.Animations = [];
+ svg.Images = [];
+ svg.ctx = ctx;
+ svg.ViewPort = new (function () {
+ this.viewPorts = [];
+ this.Clear = function() { this.viewPorts = []; };
+ this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); };
+ this.RemoveCurrent = function() { this.viewPorts.pop(); };
+ this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; };
+ this.width = function() { return this.Current().width; };
+ this.height = function() { return this.Current().height; };
+ this.ComputeSize = function(d) {
+ if (d != null && typeof d == 'number') return d;
+ if (d == 'x') return this.width();
+ if (d == 'y') return this.height();
+ return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);
+ };
+ });
+ }
+ svg.init();
+
+ // images loaded
+ svg.ImagesLoaded = function() {
+ for (var i=0; i]*>/, '');
+ var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
+ xmlDoc.async = 'false';
+ xmlDoc.loadXML(xml);
+ return xmlDoc;
+ }
+ }
+
+ svg.Property = function(name, value) {
+ this.name = name;
+ this.value = value;
+ }
+ svg.Property.prototype.getValue = function() {
+ return this.value;
+ }
+
+ svg.Property.prototype.hasValue = function() {
+ return (this.value != null && this.value != '');
+ }
+
+ // return the numerical value of the property
+ svg.Property.prototype.numValue = function() {
+ if (!this.hasValue()) return 0;
+
+ var n = parseFloat(this.value);
+ if ((this.value + '').match(/%$/)) {
+ n = n / 100.0;
+ }
+ return n;
+ }
+
+ svg.Property.prototype.valueOrDefault = function(def) {
+ if (this.hasValue()) return this.value;
+ return def;
+ }
+
+ svg.Property.prototype.numValueOrDefault = function(def) {
+ if (this.hasValue()) return this.numValue();
+ return def;
+ }
+
+ // color extensions
+ // augment the current color value with the opacity
+ svg.Property.prototype.addOpacity = function(opacityProp) {
+ var newValue = this.value;
+ if (opacityProp.value != null && opacityProp.value != '' && typeof this.value == 'string') { // can only add opacity to colors, not patterns
+ var color = new RGBColor(this.value);
+ if (color.ok) {
+ newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacityProp.numValue() + ')';
+ }
+ }
+ return new svg.Property(this.name, newValue);
+ }
+
+ // definition extensions
+ // get the definition from the definitions table
+ svg.Property.prototype.getDefinition = function() {
+ var name = this.value.match(/#([^\)'"]+)/);
+ if (name) { name = name[1]; }
+ if (!name) { name = this.value; }
+ return svg.Definitions[name];
+ }
+
+ svg.Property.prototype.isUrlDefinition = function() {
+ return this.value.indexOf('url(') == 0
+ }
+
+ svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) {
+ var def = this.getDefinition();
+
+ // gradient
+ if (def != null && def.createGradient) {
+ return def.createGradient(svg.ctx, e, opacityProp);
+ }
+
+ // pattern
+ if (def != null && def.createPattern) {
+ if (def.getHrefAttribute().hasValue()) {
+ var pt = def.attribute('patternTransform');
+ def = def.getHrefAttribute().getDefinition();
+ if (pt.hasValue()) { def.attribute('patternTransform', true).value = pt.value; }
+ }
+ return def.createPattern(svg.ctx, e);
+ }
+
+ return null;
+ }
+
+ // length extensions
+ svg.Property.prototype.getDPI = function(viewPort) {
+ return 96.0; // TODO: compute?
+ }
+
+ svg.Property.prototype.getEM = function(viewPort) {
+ var em = 12;
+
+ var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
+ if (fontSize.hasValue()) em = fontSize.toPixels(viewPort);
+
+ return em;
+ }
+
+ svg.Property.prototype.getUnits = function() {
+ var s = this.value+'';
+ return s.replace(/[0-9\.\-]/g,'');
+ }
+
+ // get the length as pixels
+ svg.Property.prototype.toPixels = function(viewPort, processPercent) {
+ if (!this.hasValue()) return 0;
+ var s = this.value+'';
+ if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
+ if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2.0;
+ if (s.match(/px$/)) return this.numValue();
+ if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1.0 / 72.0);
+ if (s.match(/pc$/)) return this.numValue() * 15;
+ if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54;
+ if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4;
+ if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort);
+ if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort);
+ var n = this.numValue();
+ if (processPercent && n < 1.0) return n * svg.ViewPort.ComputeSize(viewPort);
+ return n;
+ }
+
+ // time extensions
+ // get the time as milliseconds
+ svg.Property.prototype.toMilliseconds = function() {
+ if (!this.hasValue()) return 0;
+ var s = this.value+'';
+ if (s.match(/s$/)) return this.numValue() * 1000;
+ if (s.match(/ms$/)) return this.numValue();
+ return this.numValue();
+ }
+
+ // angle extensions
+ // get the angle as radians
+ svg.Property.prototype.toRadians = function() {
+ if (!this.hasValue()) return 0;
+ var s = this.value+'';
+ if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180.0);
+ if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200.0);
+ if (s.match(/rad$/)) return this.numValue();
+ return this.numValue() * (Math.PI / 180.0);
+ }
+
+ // text extensions
+ // get the text baseline
+ var textBaselineMapping = {
+ 'baseline': 'alphabetic',
+ 'before-edge': 'top',
+ 'text-before-edge': 'top',
+ 'middle': 'middle',
+ 'central': 'middle',
+ 'after-edge': 'bottom',
+ 'text-after-edge': 'bottom',
+ 'ideographic': 'ideographic',
+ 'alphabetic': 'alphabetic',
+ 'hanging': 'hanging',
+ 'mathematical': 'alphabetic'
+ };
+ svg.Property.prototype.toTextBaseline = function () {
+ if (!this.hasValue()) return null;
+ return textBaselineMapping[this.value];
+ }
+
+ // fonts
+ svg.Font = new (function() {
+ this.Styles = 'normal|italic|oblique|inherit';
+ this.Variants = 'normal|small-caps|inherit';
+ this.Weights = 'normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit';
+
+ this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
+ var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
+ return {
+ fontFamily: fontFamily || f.fontFamily,
+ fontSize: fontSize || f.fontSize,
+ fontStyle: fontStyle || f.fontStyle,
+ fontWeight: fontWeight || f.fontWeight,
+ fontVariant: fontVariant || f.fontVariant,
+ toString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') }
+ }
+ }
+
+ var that = this;
+ this.Parse = function(s) {
+ var f = {};
+ var d = svg.trim(svg.compressSpaces(s || '')).split(' ');
+ var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false }
+ var ff = '';
+ for (var i=0; i this.x2) this.x2 = x;
+ }
+
+ if (y != null) {
+ if (isNaN(this.y1) || isNaN(this.y2)) {
+ this.y1 = y;
+ this.y2 = y;
+ }
+ if (y < this.y1) this.y1 = y;
+ if (y > this.y2) this.y2 = y;
+ }
+ }
+ this.addX = function(x) { this.addPoint(x, null); }
+ this.addY = function(y) { this.addPoint(null, y); }
+
+ this.addBoundingBox = function(bb) {
+ this.addPoint(bb.x1, bb.y1);
+ this.addPoint(bb.x2, bb.y2);
+ }
+
+ this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {
+ var cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0)
+ var cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0)
+ var cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0)
+ var cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0)
+ this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y);
+ }
+
+ this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
+ // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
+ var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y];
+ this.addPoint(p0[0], p0[1]);
+ this.addPoint(p3[0], p3[1]);
+
+ for (var i=0; i<=1; i++) {
+ var f = function(t) {
+ return Math.pow(1-t, 3) * p0[i]
+ + 3 * Math.pow(1-t, 2) * t * p1[i]
+ + 3 * (1-t) * Math.pow(t, 2) * p2[i]
+ + Math.pow(t, 3) * p3[i];
+ }
+
+ var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
+ var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
+ var c = 3 * p1[i] - 3 * p0[i];
+
+ if (a == 0) {
+ if (b == 0) continue;
+ var t = -c / b;
+ if (0 < t && t < 1) {
+ if (i == 0) this.addX(f(t));
+ if (i == 1) this.addY(f(t));
+ }
+ continue;
+ }
+
+ var b2ac = Math.pow(b, 2) - 4 * c * a;
+ if (b2ac < 0) continue;
+ var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
+ if (0 < t1 && t1 < 1) {
+ if (i == 0) this.addX(f(t1));
+ if (i == 1) this.addY(f(t1));
+ }
+ var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
+ if (0 < t2 && t2 < 1) {
+ if (i == 0) this.addX(f(t2));
+ if (i == 1) this.addY(f(t2));
+ }
+ }
+ }
+
+ this.isPointInBox = function(x, y) {
+ return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2);
+ }
+
+ this.addPoint(x1, y1);
+ this.addPoint(x2, y2);
+ }
+
+ // transforms
+ svg.Transform = function(v) {
+ var that = this;
+ this.Type = {}
+
+ // translate
+ this.Type.translate = function(s) {
+ this.p = svg.CreatePoint(s);
+ this.apply = function(ctx) {
+ ctx.translate(this.p.x || 0.0, this.p.y || 0.0);
+ }
+ this.unapply = function(ctx) {
+ ctx.translate(-1.0 * this.p.x || 0.0, -1.0 * this.p.y || 0.0);
+ }
+ this.applyToPoint = function(p) {
+ p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
+ }
+ }
+
+ // rotate
+ this.Type.rotate = function(s) {
+ var a = svg.ToNumberArray(s);
+ this.angle = new svg.Property('angle', a[0]);
+ this.cx = a[1] || 0;
+ this.cy = a[2] || 0;
+ this.apply = function(ctx) {
+ ctx.translate(this.cx, this.cy);
+ ctx.rotate(this.angle.toRadians());
+ ctx.translate(-this.cx, -this.cy);
+ }
+ this.unapply = function(ctx) {
+ ctx.translate(this.cx, this.cy);
+ ctx.rotate(-1.0 * this.angle.toRadians());
+ ctx.translate(-this.cx, -this.cy);
+ }
+ this.applyToPoint = function(p) {
+ var a = this.angle.toRadians();
+ p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
+ p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);
+ p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]);
+ }
+ }
+
+ this.Type.scale = function(s) {
+ this.p = svg.CreatePoint(s);
+ this.apply = function(ctx) {
+ ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);
+ }
+ this.unapply = function(ctx) {
+ ctx.scale(1.0 / this.p.x || 1.0, 1.0 / this.p.y || this.p.x || 1.0);
+ }
+ this.applyToPoint = function(p) {
+ p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]);
+ }
+ }
+
+ this.Type.matrix = function(s) {
+ this.m = svg.ToNumberArray(s);
+ this.apply = function(ctx) {
+ ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
+ }
+ this.unapply = function(ctx) {
+ var a = this.m[0];
+ var b = this.m[2];
+ var c = this.m[4];
+ var d = this.m[1];
+ var e = this.m[3];
+ var f = this.m[5];
+ var g = 0.0;
+ var h = 0.0;
+ var i = 1.0;
+ var det = 1 / (a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g));
+ ctx.transform(
+ det*(e*i-f*h),
+ det*(f*g-d*i),
+ det*(c*h-b*i),
+ det*(a*i-c*g),
+ det*(b*f-c*e),
+ det*(c*d-a*f)
+ );
+ }
+ this.applyToPoint = function(p) {
+ p.applyTransform(this.m);
+ }
+ }
+
+ this.Type.SkewBase = function(s) {
+ this.base = that.Type.matrix;
+ this.base(s);
+ this.angle = new svg.Property('angle', s);
+ }
+ this.Type.SkewBase.prototype = new this.Type.matrix;
+
+ this.Type.skewX = function(s) {
+ this.base = that.Type.SkewBase;
+ this.base(s);
+ this.m = [1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0];
+ }
+ this.Type.skewX.prototype = new this.Type.SkewBase;
+
+ this.Type.skewY = function(s) {
+ this.base = that.Type.SkewBase;
+ this.base(s);
+ this.m = [1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0];
+ }
+ this.Type.skewY.prototype = new this.Type.SkewBase;
+
+ this.transforms = [];
+
+ this.apply = function(ctx) {
+ for (var i=0; i=0; i--) {
+ this.transforms[i].unapply(ctx);
+ }
+ }
+
+ this.applyToPoint = function(p) {
+ for (var i=0; i existingSpecificity) {
+ this.styles[name] = styles[name];
+ this.stylesSpecificity[name] = specificity;
+ }
+ }
+ }
+ }
+ }
+ };
+
+ if (node != null && node.nodeType == 1) { //ELEMENT_NODE
+ // add attributes
+ for (var i=0; i 0) {
+ markers.push([this.points[this.points.length-1], markers[markers.length-1][1]]);
+ }
+ return markers;
+ }
+ }
+ svg.Element.polyline.prototype = new svg.Element.PathElementBase;
+
+ // polygon element
+ svg.Element.polygon = function(node) {
+ this.base = svg.Element.polyline;
+ this.base(node);
+
+ this.basePath = this.path;
+ this.path = function(ctx) {
+ var bb = this.basePath(ctx);
+ if (ctx != null) {
+ ctx.lineTo(this.points[0].x, this.points[0].y);
+ ctx.closePath();
+ }
+ return bb;
+ }
+ }
+ svg.Element.polygon.prototype = new svg.Element.polyline;
+
+ // path element
+ svg.Element.path = function(node) {
+ this.base = svg.Element.PathElementBase;
+ this.base(node);
+
+ var d = this.attribute('d').value;
+ // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
+ d = d.replace(/,/gm,' '); // get rid of all commas
+ // As the end of a match can also be the start of the next match, we need to run this replace twice.
+ for(var i=0; i<2; i++)
+ d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm,'$1 $2'); // suffix commands with spaces
+ d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // prefix commands with spaces
+ d = d.replace(/([0-9])([+\-])/gm,'$1 $2'); // separate digits on +- signs
+ // Again, we need to run this twice to find all occurances
+ for(var i=0; i<2; i++)
+ d = d.replace(/(\.[0-9]*)(\.)/gm,'$1 $2'); // separate digits when they start with a comma
+ d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,'$1 $3 $4 '); // shorthand elliptical arc path syntax
+ d = svg.compressSpaces(d); // compress multiple spaces
+ d = svg.trim(d);
+ this.PathParser = new (function(d) {
+ this.tokens = d.split(' ');
+
+ this.reset = function() {
+ this.i = -1;
+ this.command = '';
+ this.previousCommand = '';
+ this.start = new svg.Point(0, 0);
+ this.control = new svg.Point(0, 0);
+ this.current = new svg.Point(0, 0);
+ this.points = [];
+ this.angles = [];
+ }
+
+ this.isEnd = function() {
+ return this.i >= this.tokens.length - 1;
+ }
+
+ this.isCommandOrEnd = function() {
+ if (this.isEnd()) return true;
+ return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
+ }
+
+ this.isRelativeCommand = function() {
+ switch(this.command)
+ {
+ case 'm':
+ case 'l':
+ case 'h':
+ case 'v':
+ case 'c':
+ case 's':
+ case 'q':
+ case 't':
+ case 'a':
+ case 'z':
+ return true;
+ break;
+ }
+ return false;
+ }
+
+ this.getToken = function() {
+ this.i++;
+ return this.tokens[this.i];
+ }
+
+ this.getScalar = function() {
+ return parseFloat(this.getToken());
+ }
+
+ this.nextCommand = function() {
+ this.previousCommand = this.command;
+ this.command = this.getToken();
+ }
+
+ this.getPoint = function() {
+ var p = new svg.Point(this.getScalar(), this.getScalar());
+ return this.makeAbsolute(p);
+ }
+
+ this.getAsControlPoint = function() {
+ var p = this.getPoint();
+ this.control = p;
+ return p;
+ }
+
+ this.getAsCurrentPoint = function() {
+ var p = this.getPoint();
+ this.current = p;
+ return p;
+ }
+
+ this.getReflectedControlPoint = function() {
+ if (this.previousCommand.toLowerCase() != 'c' &&
+ this.previousCommand.toLowerCase() != 's' &&
+ this.previousCommand.toLowerCase() != 'q' &&
+ this.previousCommand.toLowerCase() != 't' ){
+ return this.current;
+ }
+
+ // reflect point
+ var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
+ return p;
+ }
+
+ this.makeAbsolute = function(p) {
+ if (this.isRelativeCommand()) {
+ p.x += this.current.x;
+ p.y += this.current.y;
+ }
+ return p;
+ }
+
+ this.addMarker = function(p, from, priorTo) {
+ // if the last angle isn't filled in because we didn't have this point yet ...
+ if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length-1] == null) {
+ this.angles[this.angles.length-1] = this.points[this.points.length-1].angleTo(priorTo);
+ }
+ this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
+ }
+
+ this.addMarkerAngle = function(p, a) {
+ this.points.push(p);
+ this.angles.push(a);
+ }
+
+ this.getMarkerPoints = function() { return this.points; }
+ this.getMarkerAngles = function() {
+ for (var i=0; i 1) {
+ rx *= Math.sqrt(l);
+ ry *= Math.sqrt(l);
+ }
+ // cx', cy'
+ var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt(
+ ((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) /
+ (Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2))
+ );
+ if (isNaN(s)) s = 0;
+ var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);
+ // cx, cy
+ var centp = new svg.Point(
+ (curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y,
+ (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y
+ );
+ // vector magnitude
+ var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); }
+ // ratio between two vectors
+ var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) }
+ // angle between two vectors
+ var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); }
+ // initial angle
+ var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]);
+ // angle delta
+ var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry];
+ var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry];
+ var ad = a(u, v);
+ if (r(u,v) <= -1) ad = Math.PI;
+ if (r(u,v) >= 1) ad = 0;
+
+ // for markers
+ var dir = 1 - sweepFlag ? 1.0 : -1.0;
+ var ah = a1 + dir * (ad / 2.0);
+ var halfWay = new svg.Point(
+ centp.x + rx * Math.cos(ah),
+ centp.y + ry * Math.sin(ah)
+ );
+ pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2);
+ pp.addMarkerAngle(cp, ah - dir * Math.PI);
+
+ bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
+ if (ctx != null) {
+ var r = rx > ry ? rx : ry;
+ var sx = rx > ry ? 1 : rx / ry;
+ var sy = rx > ry ? ry / rx : 1;
+
+ ctx.translate(centp.x, centp.y);
+ ctx.rotate(xAxisRotation);
+ ctx.scale(sx, sy);
+ ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
+ ctx.scale(1/sx, 1/sy);
+ ctx.rotate(-xAxisRotation);
+ ctx.translate(-centp.x, -centp.y);
+ }
+ }
+ break;
+ case 'Z':
+ case 'z':
+ if (ctx != null) ctx.closePath();
+ pp.current = pp.start;
+ }
+ }
+
+ return bb;
+ }
+
+ this.getMarkers = function() {
+ var points = this.PathParser.getMarkerPoints();
+ var angles = this.PathParser.getMarkerAngles();
+
+ var markers = [];
+ for (var i=0; i 1) this.offset = 1;
+
+ var stopColor = this.style('stop-color', true);
+ if (stopColor.value == '') stopColor.value = '#000';
+ if (this.style('stop-opacity').hasValue()) stopColor = stopColor.addOpacity(this.style('stop-opacity'));
+ this.color = stopColor.value;
+ }
+ svg.Element.stop.prototype = new svg.Element.ElementBase;
+
+ // animation base element
+ svg.Element.AnimateBase = function(node) {
+ this.base = svg.Element.ElementBase;
+ this.base(node);
+
+ svg.Animations.push(this);
+
+ this.duration = 0.0;
+ this.begin = this.attribute('begin').toMilliseconds();
+ this.maxDuration = this.begin + this.attribute('dur').toMilliseconds();
+
+ this.getProperty = function() {
+ var attributeType = this.attribute('attributeType').value;
+ var attributeName = this.attribute('attributeName').value;
+
+ if (attributeType == 'CSS') {
+ return this.parent.style(attributeName, true);
+ }
+ return this.parent.attribute(attributeName, true);
+ };
+
+ this.initialValue = null;
+ this.initialUnits = '';
+ this.removed = false;
+
+ this.calcValue = function() {
+ // OVERRIDE ME!
+ return '';
+ }
+
+ this.update = function(delta) {
+ // set initial value
+ if (this.initialValue == null) {
+ this.initialValue = this.getProperty().value;
+ this.initialUnits = this.getProperty().getUnits();
+ }
+
+ // if we're past the end time
+ if (this.duration > this.maxDuration) {
+ // loop for indefinitely repeating animations
+ if (this.attribute('repeatCount').value == 'indefinite'
+ || this.attribute('repeatDur').value == 'indefinite') {
+ this.duration = 0.0
+ }
+ else if (this.attribute('fill').valueOrDefault('remove') == 'freeze' && !this.frozen) {
+ this.frozen = true;
+ this.parent.animationFrozen = true;
+ this.parent.animationFrozenValue = this.getProperty().value;
+ }
+ else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) {
+ this.removed = true;
+ this.getProperty().value = this.parent.animationFrozen ? this.parent.animationFrozenValue : this.initialValue;
+ return true;
+ }
+ return false;
+ }
+ this.duration = this.duration + delta;
+
+ // if we're past the begin time
+ var updated = false;
+ if (this.begin < this.duration) {
+ var newValue = this.calcValue(); // tween
+
+ if (this.attribute('type').hasValue()) {
+ // for transform, etc.
+ var type = this.attribute('type').value;
+ newValue = type + '(' + newValue + ')';
+ }
+
+ this.getProperty().value = newValue;
+ updated = true;
+ }
+
+ return updated;
+ }
+
+ this.from = this.attribute('from');
+ this.to = this.attribute('to');
+ this.values = this.attribute('values');
+ if (this.values.hasValue()) this.values.value = this.values.value.split(';');
+
+ // fraction of duration we've covered
+ this.progress = function() {
+ var ret = { progress: (this.duration - this.begin) / (this.maxDuration - this.begin) };
+ if (this.values.hasValue()) {
+ var p = ret.progress * (this.values.value.length - 1);
+ var lb = Math.floor(p), ub = Math.ceil(p);
+ ret.from = new svg.Property('from', parseFloat(this.values.value[lb]));
+ ret.to = new svg.Property('to', parseFloat(this.values.value[ub]));
+ ret.progress = (p - lb) / (ub - lb);
+ }
+ else {
+ ret.from = this.from;
+ ret.to = this.to;
+ }
+ return ret;
+ }
+ }
+ svg.Element.AnimateBase.prototype = new svg.Element.ElementBase;
+
+ // animate element
+ svg.Element.animate = function(node) {
+ this.base = svg.Element.AnimateBase;
+ this.base(node);
+
+ this.calcValue = function() {
+ var p = this.progress();
+
+ // tween value linearly
+ var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress;
+ return newValue + this.initialUnits;
+ };
+ }
+ svg.Element.animate.prototype = new svg.Element.AnimateBase;
+
+ // animate color element
+ svg.Element.animateColor = function(node) {
+ this.base = svg.Element.AnimateBase;
+ this.base(node);
+
+ this.calcValue = function() {
+ var p = this.progress();
+ var from = new RGBColor(p.from.value);
+ var to = new RGBColor(p.to.value);
+
+ if (from.ok && to.ok) {
+ // tween color linearly
+ var r = from.r + (to.r - from.r) * p.progress;
+ var g = from.g + (to.g - from.g) * p.progress;
+ var b = from.b + (to.b - from.b) * p.progress;
+ return 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')';
+ }
+ return this.attribute('from').value;
+ };
+ }
+ svg.Element.animateColor.prototype = new svg.Element.AnimateBase;
+
+ // animate transform element
+ svg.Element.animateTransform = function(node) {
+ this.base = svg.Element.AnimateBase;
+ this.base(node);
+
+ this.calcValue = function() {
+ var p = this.progress();
+
+ // tween value linearly
+ var from = svg.ToNumberArray(p.from.value);
+ var to = svg.ToNumberArray(p.to.value);
+ var newValue = '';
+ for (var i=0; i startI && child.attribute('x').hasValue()) break; // new group
+ width += child.measureTextRecursive(ctx);
+ }
+ return -1 * (textAnchor == 'end' ? width : width / 2.0);
+ }
+ return 0;
+ }
+
+ this.renderChild = function(ctx, textParent, parent, i) {
+ var child = parent.children[i];
+ if (child.attribute('x').hasValue()) {
+ child.x = child.attribute('x').toPixels('x') + textParent.getAnchorDelta(ctx, parent, i);
+ if (child.attribute('dx').hasValue()) child.x += child.attribute('dx').toPixels('x');
+ }
+ else {
+ if (child.attribute('dx').hasValue()) textParent.x += child.attribute('dx').toPixels('x');
+ child.x = textParent.x;
+ }
+ textParent.x = child.x + child.measureText(ctx);
+
+ if (child.attribute('y').hasValue()) {
+ child.y = child.attribute('y').toPixels('y');
+ if (child.attribute('dy').hasValue()) child.y += child.attribute('dy').toPixels('y');
+ }
+ else {
+ if (child.attribute('dy').hasValue()) textParent.y += child.attribute('dy').toPixels('y');
+ child.y = textParent.y;
+ }
+ textParent.y = child.y;
+
+ child.render(ctx);
+
+ for (var i=0; i0 && text[i-1]!=' ' && i0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial';
+ if (typeof font.glyphs[c] != 'undefined') {
+ glyph = font.glyphs[c][arabicForm];
+ if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c];
+ }
+ }
+ else {
+ glyph = font.glyphs[c];
+ }
+ if (glyph == null) glyph = font.missingGlyph;
+ return glyph;
+ }
+
+ this.renderChildren = function(ctx) {
+ var customFont = this.parent.style('font-family').getDefinition();
+ if (customFont != null) {
+ var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
+ var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
+ var text = this.getText();
+ if (customFont.isRTL) text = text.split("").reverse().join("");
+
+ var dx = svg.ToNumberArray(this.parent.attribute('dx').value);
+ for (var i=0; i 0) { return ''; }
+ return this.text;
+ }
+ }
+ svg.Element.tspan.prototype = new svg.Element.TextElementBase;
+
+ // tref
+ svg.Element.tref = function(node) {
+ this.base = svg.Element.TextElementBase;
+ this.base(node);
+
+ this.getText = function() {
+ var element = this.getHrefAttribute().getDefinition();
+ if (element != null) return element.children[0].getText();
+ }
+ }
+ svg.Element.tref.prototype = new svg.Element.TextElementBase;
+
+ // a element
+ svg.Element.a = function(node) {
+ this.base = svg.Element.TextElementBase;
+ this.base(node);
+
+ this.hasText = node.childNodes.length > 0;
+ for (var i=0; i 0) {
+ // render as temporary group
+ var g = new svg.Element.g();
+ g.children = this.children;
+ g.parent = this;
+ g.render(ctx);
+ }
+ }
+
+ this.onclick = function() {
+ window.open(this.getHrefAttribute().value);
+ }
+
+ this.onmousemove = function() {
+ svg.ctx.canvas.style.cursor = 'pointer';
+ }
+ }
+ svg.Element.a.prototype = new svg.Element.TextElementBase;
+
+ // image element
+ svg.Element.image = function(node) {
+ this.base = svg.Element.RenderedElementBase;
+ this.base(node);
+
+ var href = this.getHrefAttribute().value;
+ if (href == '') { return; }
+ var isSvg = href.match(/\.svg$/)
+
+ svg.Images.push(this);
+ this.loaded = false;
+ if (!isSvg) {
+ this.img = document.createElement('img');
+ if (svg.opts['useCORS'] == true) { this.img.crossOrigin = 'Anonymous'; }
+ var self = this;
+ this.img.onload = function() { self.loaded = true; }
+ this.img.onerror = function() { svg.log('ERROR: image "' + href + '" not found'); self.loaded = true; }
+ this.img.src = href;
+ }
+ else {
+ this.img = svg.ajax(href);
+ this.loaded = true;
+ }
+
+ this.renderChildren = function(ctx) {
+ var x = this.attribute('x').toPixels('x');
+ var y = this.attribute('y').toPixels('y');
+
+ var width = this.attribute('width').toPixels('x');
+ var height = this.attribute('height').toPixels('y');
+ if (width == 0 || height == 0) return;
+
+ ctx.save();
+ if (isSvg) {
+ ctx.drawSvg(this.img, x, y, width, height);
+ }
+ else {
+ ctx.translate(x, y);
+ svg.AspectRatio(ctx,
+ this.attribute('preserveAspectRatio').value,
+ width,
+ this.img.width,
+ height,
+ this.img.height,
+ 0,
+ 0);
+ ctx.drawImage(this.img, 0, 0);
+ }
+ ctx.restore();
+ }
+
+ this.getBoundingBox = function() {
+ var x = this.attribute('x').toPixels('x');
+ var y = this.attribute('y').toPixels('y');
+ var width = this.attribute('width').toPixels('x');
+ var height = this.attribute('height').toPixels('y');
+ return new svg.BoundingBox(x, y, x + width, y + height);
+ }
+ }
+ svg.Element.image.prototype = new svg.Element.RenderedElementBase;
+
+ // group element
+ svg.Element.g = function(node) {
+ this.base = svg.Element.RenderedElementBase;
+ this.base(node);
+
+ this.getBoundingBox = function() {
+ var bb = new svg.BoundingBox();
+ for (var i=0; i 0) {
+ var urlStart = srcs[s].indexOf('url');
+ var urlEnd = srcs[s].indexOf(')', urlStart);
+ var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);
+ var doc = svg.parseXml(svg.ajax(url));
+ var fonts = doc.getElementsByTagName('font');
+ for (var f=0; f label > input,\n.context-menu-item > label > textarea {\n -webkit-user-select: text;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n}\n\n.context-menu-item.hover {\n cursor: pointer;\n background-color: #39F;\n}\n\n.context-menu-item.disabled {\n color: #666;\n}\n\n.context-menu-input.hover,\n.context-menu-item.disabled.hover {\n cursor: default;\n background-color: #EEE;\n}\n\n.context-menu-submenu:after {\n content: \">\";\n color: #666;\n position: absolute;\n top: 0;\n right: 3px;\n z-index: 1;\n}\n\n/* icons\n #protip:\n In case you want to use sprites for icons (which I would suggest you do) have a look at\n http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement\n .context-menu-item.icon:before {}\n */\n.context-menu-item.icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; }\n\n/* vertically align inside labels */\n.context-menu-input > label > * { vertical-align: top; }\n\n/* position checkboxes and radios as icons */\n.context-menu-input > label > input[type=\"checkbox\"],\n.context-menu-input > label > input[type=\"radio\"] {\n margin-left: -17px;\n}\n.context-menu-input > label > span {\n margin-left: 5px;\n}\n\n.context-menu-input > label,\n.context-menu-input > label > input[type=\"text\"],\n.context-menu-input > label > textarea,\n.context-menu-input > label > select {\n display: block;\n width: 100%;\n\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n -ms-box-sizing: border-box;\n -o-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.context-menu-input > label > textarea {\n height: 100px;\n}\n.context-menu-item > .context-menu-list {\n display: none;\n /* re-positioned by js */\n right: -5px;\n top: 5px;\n}\n\n.context-menu-item.hover > .context-menu-list {\n display: block;\n}\n\n.context-menu-accesskey {\n text-decoration: underline;\n}\n", ""]);
+
+// exports
+
+
+/***/ }),
+
+/***/ "./node_modules/css-loader/lib/css-base.js":
+/*!*************************************************!*\
+ !*** ./node_modules/css-loader/lib/css-base.js ***!
+ \*************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+// css base code, injected by the css-loader
+module.exports = function(useSourceMap) {
+ var list = [];
+
+ // return the list of modules as css string
+ list.toString = function toString() {
+ return this.map(function (item) {
+ var content = cssWithMappingToString(item, useSourceMap);
+ if(item[2]) {
+ return "@media " + item[2] + "{" + content + "}";
+ } else {
+ return content;
+ }
+ }).join("");
+ };
+
+ // import a list of modules into the list
+ list.i = function(modules, mediaQuery) {
+ if(typeof modules === "string")
+ modules = [[null, modules, ""]];
+ var alreadyImportedModules = {};
+ for(var i = 0; i < this.length; i++) {
+ var id = this[i][0];
+ if(typeof id === "number")
+ alreadyImportedModules[id] = true;
+ }
+ for(i = 0; i < modules.length; i++) {
+ var item = modules[i];
+ // skip already imported module
+ // this implementation is not 100% perfect for weird media query combinations
+ // when a module is imported multiple times with different media queries.
+ // I hope this will never occur (Hey this way we have smaller bundles)
+ if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
+ if(mediaQuery && !item[2]) {
+ item[2] = mediaQuery;
+ } else if(mediaQuery) {
+ item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
+ }
+ list.push(item);
+ }
+ }
+ };
+ return list;
+};
+
+function cssWithMappingToString(item, useSourceMap) {
+ var content = item[1] || '';
+ var cssMapping = item[3];
+ if (!cssMapping) {
+ return content;
+ }
+
+ if (useSourceMap && typeof btoa === 'function') {
+ var sourceMapping = toComment(cssMapping);
+ var sourceURLs = cssMapping.sources.map(function (source) {
+ return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
+ });
+
+ return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
+ }
+
+ return [content].join('\n');
+}
+
+// Adapted from convert-source-map (MIT)
+function toComment(sourceMap) {
+ // eslint-disable-next-line no-undef
+ var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
+ var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
+
+ return '/*# ' + data + ' */';
+}
+
+
+/***/ }),
+
+/***/ "./node_modules/raw-loader/index.js!./src/lib/Class.exec.js":
+/*!*********************************************************!*\
+ !*** ./node_modules/raw-loader!./src/lib/Class.exec.js ***!
+ \*********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "/* \n * Simple JavaScript Inheritance \n * By John Resig http://ejohn.org/ \n * MIT Licensed. \n * \n ****************************************************** \n * Example Usage \n ****************************************************** \n var Person = Class.extend({ \n init: function(isDancing){ \n this.dancing = isDancing; \n }, \n dance: function(){ \n return this.dancing; \n } \n}); \n\nvar Ninja = Person.extend({ \n init: function(){ \n this._super( false ); \n }, \n dance: function(){ \n // Call the inherited version of dance() \n return this._super(); \n }, \n swingSword: function(){ \n return true; \n } \n}); \n\nvar p = new Person(true); \np.dance(); // => true \n\nvar n = new Ninja(); \nn.dance(); // => false \nn.swingSword(); // => true \n\n// Should all be true \np instanceof Person && p instanceof Class && \nn instanceof Ninja && n instanceof Person && n instanceof Class \n\n ****************************************************** \n */ \n \n// Inspired by base2 and Prototype \n(function(){ \n var fnTest = /xyz/.test(function(){xyz;}) ? /\\b_super\\b/ : /.*/; \n\n // The base Class implementation (does nothing) \n this.Class = function(){}; \n \n\n // Create a new Class that inherits from this class \n Class.extend = function(prop) { \n var _super = this.prototype; \n \n // Instantiate a base class (but only create the instance, \n // don't run the init constructor) \n initializing = true; \n var prototype = new this(); \n initializing = false; \n \n \n // Copy the properties over onto the new prototype \n for (var name in prop) { \n // Check if we're overwriting an existing function \n prototype[name] = typeof prop[name] == \"function\" && \n typeof _super[name] == \"function\" && fnTest.test(prop[name]) ? \n (function(name, fn){ \n return function() { \n var tmp = this._super; \n \n // Add a new ._super() method that is the same method \n // but on the super-class \n this._super = _super[name]; \n \n // The method only need to be bound temporarily, so we \n // remove it when we're done executing \n var ret = fn.apply(this, arguments); \n this._super = tmp; \n \n return ret; \n }; \n })(name, prop[name]) : \n prop[name]; \n } \n \n // The dummy class constructor \n function Class() { \n // All construction is actually done in the init method \n if ( !initializing && this.init ) \n this.init.apply(this, arguments); \n } \n \n // Populate our constructed prototype object \n Class.prototype = prototype; \n \n // Enforce the constructor to be what we expect \n Class.prototype.constructor = Class; \n\n // And make this class extendable \n Class.extend = arguments.callee; \n \n // EXTENSION BY Draw2D.org to inject methods into an existing class to provide plugins or \n // bugfixes for further releases \n // \n Class.inject = function (prop) { \n var proto = this.prototype; \n var parent = {}; \n for (var name in prop) { \n if (typeof (prop[name]) == \"function\" && typeof (proto[name]) == \"function\" && fnTest.test(prop[name])) { \n parent[name] = proto[name]; \n proto[name] = (function (name, fn) { \n return function () { \n var tmp = this.parent; \n this.parent = parent[name]; \n var ret = fn.apply(this, arguments); \n this.parent = tmp; \n return ret; \n }; \n })(name, prop[name]); \n } else { \n proto[name] = prop[name]; \n } \n } \n }; \n \n return Class; \n }; \n})();\n \n"
+
+/***/ }),
+
+/***/ "./node_modules/raw-loader/index.js!./src/lib/pathfinding.exec.js":
+/*!***************************************************************!*\
+ !*** ./node_modules/raw-loader!./src/lib/pathfinding.exec.js ***!
+ \***************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "var PF=function(){var e=function(t,n){var r=e.resolve(t,n||\"/\"),i=e.modules[r];if(!i)throw new Error(\"Failed to resolve module \"+t+\", tried \"+r);var s=i._cached?i._cached:i();return s};return e.paths=[],e.modules={},e.extensions=[\".js\",\".coffee\"],e._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},e.resolve=function(){return function(t,n){function u(t){if(e.modules[t])return t;for(var n=0;n=0;i--){if(t[i]===\"node_modules\")continue;var s=t.slice(0,i+1).join(\"/\")+\"/node_modules\";n.push(s)}return n}n||(n=\"/\");if(e._core[t])return t;var r=e.modules.path();n=r.resolve(\"/\",n);var i=n||\"/\";if(t.match(/^(?:\\.\\.?\\/|\\/)/)){var s=u(r.resolve(i,t))||a(r.resolve(i,t));if(s)return s}var o=f(t,i);if(o)return o;throw new Error(\"Cannot find module '\"+t+\"'\")}}(),e.alias=function(t,n){var r=e.modules.path(),i=null;try{i=e.resolve(t+\"/package.json\",\"/\")}catch(s){i=e.resolve(t,\"/\")}var o=r.dirname(i),u=(Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t})(e.modules);for(var a=0;a0){var n=e.shift();n()}}},!0),function(n){t?(e.push(n),window.postMessage(\"browserify-tick\",\"*\")):setTimeout(n,0)}}()),process.title||(process.title=\"browser\"),process.binding||(process.binding=function(t){if(t===\"evals\")return e(\"vm\");throw new Error(\"No such module\")}),process.cwd||(process.cwd=function(){return\".\"}),process.env||(process.env={}),process.argv||(process.argv=[]),e.define(\"path\",function(e,t,n,r,i){function s(e,t){var n=[];for(var r=0;r=0;r--){var i=e[r];i==\".\"?e.splice(r,1):i===\"..\"?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift(\"..\");return e}var u=/^(.+\\/(?!$)|\\/)?((?:.+?)?(\\.[^.]*)?)$/;n.resolve=function(){var e=\"\",t=!1;for(var n=arguments.length;n>=-1&&!t;n--){var r=n>=0?arguments[n]:process.cwd();if(typeof r!=\"string\"||!r)continue;e=r+\"/\"+e,t=r.charAt(0)===\"/\"}return e=o(s(e.split(\"/\"),function(e){return!!e}),!t).join(\"/\"),(t?\"/\":\"\")+e||\".\"},n.normalize=function(e){var t=e.charAt(0)===\"/\",n=e.slice(-1)===\"/\";return e=o(s(e.split(\"/\"),function(e){return!!e}),!t).join(\"/\"),!e&&!t&&(e=\".\"),e&&n&&(e+=\"/\"),(t?\"/\":\"\")+e},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(s(e,function(e,t){return e&&typeof e==\"string\"}).join(\"/\"))},n.dirname=function(e){var t=u.exec(e)[1]||\"\",n=!1;return t?t.length===1||n&&t.length<=3&&t.charAt(1)===\":\"?t:t.substring(0,t.length-1):\".\"},n.basename=function(e,t){var n=u.exec(e)[2]||\"\";return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},n.extname=function(e){return u.exec(e)[3]||\"\"}}),e.define(\"/core/Node.js\",function(e,t,n,r,i){function s(e,t,n){this.x=e,this.y=t,this.walkable=n===undefined?!0:n}t.exports=s}),e.define(\"/core/Grid.js\",function(e,t,n,r,i){function o(e,t,n){this.width=e,this.height=t,this.nodes=this._buildNodes(e,t,n)}var s=e(\"./Node\");o.prototype._buildNodes=function(e,t,n){var r,i,o=new Array(t),u;for(r=0;r=0&&e=0&&tt?1:0},f=function(e,t,i,s,o){var u;i==null&&(i=0),o==null&&(o=n);if(i<0)throw new Error(\"lo must be non-negative\");s==null&&(s=e.length);while(o(i,s)<0)u=r((i+s)/2),o(t,e[u])<0?s=u:i=u+1;return[].splice.apply(e,[i,i-i].concat(t)),t},o=function(e,t,r){return r==null&&(r=n),e.push(t),d(e,0,e.length-1,r)},s=function(e,t){var r,i;return t==null&&(t=n),r=e.pop(),e.length?(i=e[0],e[0]=r,v(e,0,t)):i=r,i},a=function(e,t,r){var i;return r==null&&(r=n),i=e[0],e[0]=t,v(e,0,r),i},u=function(e,t,r){var i;return r==null&&(r=n),e.length&&r(e[0],t)<0&&(i=[e[0],t],t=i[0],e[0]=i[1],v(e,0,r)),t},i=function(e,t){var i,s,o,u,a,f,l,c;t==null&&(t=n),f=function(){c=[];for(var t=0,n=r(e.length/2);0<=n?tn;0<=n?t++:t--)c.push(t);return c}.apply(this).reverse(),l=[];for(s=0,u=f.length;sm;u=0<=m?++p:--p)g.push(s(e,r));return g},d=function(e,t,r,i){var s,o,u;i==null&&(i=n),s=e[r];while(r>t){u=r-1>>1,o=e[u];if(i(s,o)<0){e[r]=o,r=u;continue}break}return e[r]=s},v=function(e,t,r){var i,s,o,u,a;r==null&&(r=n),s=e.length,a=t,o=e[t],i=2*t+1;while(i-f&&(l-=f,e+=o),c Arguments\n\n - name (string) name of the *event*, dot (`.`) or slash (`/`) separated\n - scope (object) context for the event handlers\n - varargs (...) the rest of arguments will be sent to event handlers\n\n = (object) array of returned values from the listeners\n \\*/\n eve = function (name, scope) {\n name = String(name);\n var e = events,\n oldstop = stop,\n args = Array.prototype.slice.call(arguments, 2),\n listeners = eve.listeners(name),\n z = 0,\n f = false,\n l,\n indexed = [],\n queue = {},\n out = [],\n ce = current_event,\n errors = [];\n current_event = name;\n stop = 0;\n for (var i = 0, ii = listeners.length; i < ii; i++) if (\"zIndex\" in listeners[i]) {\n indexed.push(listeners[i].zIndex);\n if (listeners[i].zIndex < 0) {\n queue[listeners[i].zIndex] = listeners[i];\n }\n }\n indexed.sort(numsort);\n while (indexed[z] < 0) {\n l = queue[indexed[z++]];\n out.push(l.apply(scope, args));\n if (stop) {\n stop = oldstop;\n return out;\n }\n }\n for (i = 0; i < ii; i++) {\n l = listeners[i];\n if (\"zIndex\" in l) {\n if (l.zIndex == indexed[z]) {\n out.push(l.apply(scope, args));\n if (stop) {\n break;\n }\n do {\n z++;\n l = queue[indexed[z]];\n l && out.push(l.apply(scope, args));\n if (stop) {\n break;\n }\n } while (l)\n } else {\n queue[l.zIndex] = l;\n }\n } else {\n out.push(l.apply(scope, args));\n if (stop) {\n break;\n }\n }\n }\n stop = oldstop;\n current_event = ce;\n return out.length ? out : null;\n };\n // Undocumented. Debug only.\n eve._events = events;\n /*\\\n * eve.listeners\n [ method ]\n\n * Internal method which gives you array of all event handlers that will be triggered by the given `name`.\n\n > Arguments\n\n - name (string) name of the event, dot (`.`) or slash (`/`) separated\n\n = (array) array of event handlers\n \\*/\n eve.listeners = function (name) {\n var names = name.split(separator),\n e = events,\n item,\n items,\n k,\n i,\n ii,\n j,\n jj,\n nes,\n es = [e],\n out = [];\n for (i = 0, ii = names.length; i < ii; i++) {\n nes = [];\n for (j = 0, jj = es.length; j < jj; j++) {\n e = es[j].n;\n items = [e[names[i]], e[wildcard]];\n k = 2;\n while (k--) {\n item = items[k];\n if (item) {\n nes.push(item);\n out = out.concat(item.f || []);\n }\n }\n }\n es = nes;\n }\n return out;\n };\n\n /*\\\n * eve.on\n [ method ]\n **\n * Binds given event handler with a given name. You can use wildcards “`*`†for the names:\n | eve.on(\"*.under.*\", f);\n | eve(\"mouse.under.floor\"); // triggers f\n * Use @eve to trigger the listener.\n **\n > Arguments\n **\n - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n - f (function) event handler function\n **\n = (function) returned function accepts a single numeric parameter that represents z-index of the handler. It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment.\n > Example:\n | eve.on(\"mouse\", eatIt)(2);\n | eve.on(\"mouse\", scream);\n | eve.on(\"mouse\", catchIt)(1);\n * This will ensure that `catchIt()` function will be called before `eatIt()`.\n *\n * If you want to put your handler before non-indexed handlers, specify a negative value.\n * Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in caseâ€.\n \\*/\n eve.on = function (name, f) {\n name = String(name);\n if (typeof f != \"function\") {\n return function () {};\n }\n var names = name.split(separator),\n e = events;\n for (var i = 0, ii = names.length; i < ii; i++) {\n e = e.n;\n e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}});\n }\n e.f = e.f || [];\n for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {\n return fun;\n }\n e.f.push(f);\n return function (zIndex) {\n if (+zIndex == +zIndex) {\n f.zIndex = +zIndex;\n }\n };\n };\n /*\\\n * eve.f\n [ method ]\n **\n * Returns function that will fire given event with optional arguments.\n * Arguments that will be passed to the result function will be also\n * concated to the list of final arguments.\n | el.onclick = eve.f(\"click\", 1, 2);\n | eve.on(\"click\", function (a, b, c) {\n | console.log(a, b, c); // 1, 2, [event object]\n | });\n > Arguments\n - event (string) event name\n - varargs (…) and any other arguments\n = (function) possible event handler function\n \\*/\n eve.f = function (event) {\n var attrs = [].slice.call(arguments, 1);\n return function () {\n eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0)));\n };\n };\n /*\\\n * eve.stop\n [ method ]\n **\n * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing.\n \\*/\n eve.stop = function () {\n stop = 1;\n };\n /*\\\n * eve.nt\n [ method ]\n **\n * Could be used inside event handler to figure out actual name of the event.\n **\n > Arguments\n **\n - subname (string) #optional subname of the event\n **\n = (string) name of the event, if `subname` is not specified\n * or\n = (boolean) `true`, if current event’s name contains `subname`\n \\*/\n eve.nt = function (subname) {\n if (subname) {\n return new RegExp(\"(?:\\\\.|\\\\/|^)\" + subname + \"(?:\\\\.|\\\\/|$)\").test(current_event);\n }\n return current_event;\n };\n /*\\\n * eve.nts\n [ method ]\n **\n * Could be used inside event handler to figure out actual name of the event.\n **\n **\n = (array) names of the event\n \\*/\n eve.nts = function () {\n return current_event.split(separator);\n };\n /*\\\n * eve.off\n [ method ]\n **\n * Removes given function from the list of event listeners assigned to given name.\n * If no arguments specified all the events will be cleared.\n **\n > Arguments\n **\n - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n - f (function) event handler function\n \\*/\n /*\\\n * eve.unbind\n [ method ]\n **\n * See @eve.off\n \\*/\n eve.off = eve.unbind = function (name, f) {\n if (!name) {\n eve._events = events = {n: {}};\n return;\n }\n var names = name.split(separator),\n e,\n key,\n splice,\n i, ii, j, jj,\n cur = [events];\n for (i = 0, ii = names.length; i < ii; i++) {\n for (j = 0; j < cur.length; j += splice.length - 2) {\n splice = [j, 1];\n e = cur[j].n;\n if (names[i] != wildcard) {\n if (e[names[i]]) {\n splice.push(e[names[i]]);\n }\n } else {\n for (key in e) if (e[has](key)) {\n splice.push(e[key]);\n }\n }\n cur.splice.apply(cur, splice);\n }\n }\n for (i = 0, ii = cur.length; i < ii; i++) {\n e = cur[i];\n while (e.n) {\n if (f) {\n if (e.f) {\n for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {\n e.f.splice(j, 1);\n break;\n }\n !e.f.length && delete e.f;\n }\n for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n var funcs = e.n[key].f;\n for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {\n funcs.splice(j, 1);\n break;\n }\n !funcs.length && delete e.n[key].f;\n }\n } else {\n delete e.f;\n for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n delete e.n[key].f;\n }\n }\n e = e.n;\n }\n }\n };\n /*\\\n * eve.once\n [ method ]\n **\n * Binds given event handler with a given name to only run once then unbind itself.\n | eve.once(\"login\", f);\n | eve(\"login\"); // triggers f\n | eve(\"login\"); // no listeners\n * Use @eve to trigger the listener.\n **\n > Arguments\n **\n - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n - f (function) event handler function\n **\n = (function) same return function as @eve.on\n \\*/\n eve.once = function (name, f) {\n var f2 = function () {\n eve.unbind(name, f2);\n return f.apply(this, arguments);\n };\n return eve.on(name, f2);\n };\n /*\\\n * eve.version\n [ property (string) ]\n **\n * Current version of the library.\n \\*/\n eve.version = version;\n eve.toString = function () {\n return \"You are running Eve \" + version;\n };\n\n return eve;\n}));\n\n// ┌────────────────────────────────────────────────────────────────────┠\\\\\n// │ Raphaël 2.1.4 - JavaScript Vector Library │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Core Module │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\\\\n// └────────────────────────────────────────────────────────────────────┘ \\\\\n\n(function (glob, factory) {\n if (typeof define === \"function\" && define.amd) {\n define(\"raphael.core\", [\"eve\"], function(eve) {\n return factory(eve);\n });\n } else if (typeof exports === \"object\") {\n module.exports = factory(require(\"eve\"));\n } else {\n glob.Raphael = factory(glob.eve);\n }\n}(this, function (eve) {\n /*\\\n * Raphael\n [ method ]\n **\n * Creates a canvas object on which to draw.\n * You must do this first, as all future calls to drawing methods\n * from this instance will be bound to this canvas.\n > Parameters\n **\n - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface\n - width (number)\n - height (number)\n - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n * or\n - x (number)\n - y (number)\n - width (number)\n - height (number)\n - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n * or\n - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, }). See @Paper.add.\n - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n * or\n - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad†event. In this case method returns `undefined`.\n = (object) @Paper\n > Usage\n | // Each of the following examples create a canvas\n | // that is 320px wide by 200px high.\n | // Canvas is created at the viewport’s 10,50 coordinate.\n | var paper = Raphael(10, 50, 320, 200);\n | // Canvas is created at the top left corner of the #notepad element\n | // (or its top right corner in dir=\"rtl\" elements)\n | var paper = Raphael(document.getElementById(\"notepad\"), 320, 200);\n | // Same as above\n | var paper = Raphael(\"notepad\", 320, 200);\n | // Image dump\n | var set = Raphael([\"notepad\", 320, 200, {\n | type: \"rect\",\n | x: 10,\n | y: 10,\n | width: 25,\n | height: 25,\n | stroke: \"#f00\"\n | }, {\n | type: \"text\",\n | x: 30,\n | y: 40,\n | text: \"Dump\"\n | }]);\n \\*/\n function R(first) {\n if (R.is(first, \"function\")) {\n return loaded ? first() : eve.on(\"raphael.DOMload\", first);\n } else if (R.is(first, array)) {\n return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);\n } else {\n var args = Array.prototype.slice.call(arguments, 0);\n if (R.is(args[args.length - 1], \"function\")) {\n var f = args.pop();\n return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on(\"raphael.DOMload\", function () {\n f.call(R._engine.create[apply](R, args));\n });\n } else {\n return R._engine.create[apply](R, arguments);\n }\n }\n }\n R.version = \"2.1.4\";\n R.eve = eve;\n var loaded,\n separator = /[, ]+/,\n elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},\n formatrg = /\\{(\\d+)\\}/g,\n proto = \"prototype\",\n has = \"hasOwnProperty\",\n g = {\n doc: document,\n win: window\n },\n oldRaphael = {\n was: Object.prototype[has].call(g.win, \"Raphael\"),\n is: g.win.Raphael\n },\n Paper = function () {\n /*\\\n * Paper.ca\n [ property (object) ]\n **\n * Shortcut for @Paper.customAttributes\n \\*/\n /*\\\n * Paper.customAttributes\n [ property (object) ]\n **\n * If you have a set of attributes that you would like to represent\n * as a function of some number you can do it easily with custom attributes:\n > Usage\n | paper.customAttributes.hue = function (num) {\n | num = num % 1;\n | return {fill: \"hsb(\" + num + \", 0.75, 1)\"};\n | };\n | // Custom attribute “hue†will change fill\n | // to be given hue with fixed saturation and brightness.\n | // Now you can use it like this:\n | var c = paper.circle(10, 10, 10).attr({hue: .45});\n | // or even like this:\n | c.animate({hue: 1}, 1e3);\n |\n | // You could also create custom attribute\n | // with multiple parameters:\n | paper.customAttributes.hsb = function (h, s, b) {\n | return {fill: \"hsb(\" + [h, s, b].join(\",\") + \")\"};\n | };\n | c.attr({hsb: \"0.5 .8 1\"});\n | c.animate({hsb: [1, 0, 0.5]}, 1e3);\n \\*/\n this.ca = this.customAttributes = {};\n },\n paperproto,\n appendChild = \"appendChild\",\n apply = \"apply\",\n concat = \"concat\",\n supportsTouch = ('ontouchstart' in g.win) || g.win.DocumentTouch && g.doc instanceof DocumentTouch, //taken from Modernizr touch test\n E = \"\",\n S = \" \",\n Str = String,\n split = \"split\",\n events = \"click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel\"[split](S),\n touchMap = {\n mousedown: \"touchstart\",\n mousemove: \"touchmove\",\n mouseup: \"touchend\"\n },\n lowerCase = Str.prototype.toLowerCase,\n math = Math,\n mmax = math.max,\n mmin = math.min,\n abs = math.abs,\n pow = math.pow,\n PI = math.PI,\n nu = \"number\",\n string = \"string\",\n array = \"array\",\n toString = \"toString\",\n fillString = \"fill\",\n objectToString = Object.prototype.toString,\n paper = {},\n push = \"push\",\n ISURL = R._ISURL = /^url\\(['\"]?(.+?)['\"]?\\)$/i,\n colourRegExp = /^\\s*((#[a-f\\d]{6})|(#[a-f\\d]{3})|rgba?\\(\\s*([\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?(?:\\s*,\\s*[\\d\\.]+%?)?)\\s*\\)|hsba?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\)|hsla?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\))\\s*$/i,\n isnan = {\"NaN\": 1, \"Infinity\": 1, \"-Infinity\": 1},\n bezierrg = /^(?:cubic-)?bezier\\(([^,]+),([^,]+),([^,]+),([^\\)]+)\\)/,\n round = math.round,\n setAttribute = \"setAttribute\",\n toFloat = parseFloat,\n toInt = parseInt,\n upperCase = Str.prototype.toUpperCase,\n availableAttrs = R._availableAttrs = {\n \"arrow-end\": \"none\",\n \"arrow-start\": \"none\",\n blur: 0,\n \"clip-rect\": \"0 0 1e9 1e9\",\n cursor: \"default\",\n cx: 0,\n cy: 0,\n fill: \"#fff\",\n \"fill-opacity\": 1,\n font: '10px \"Arial\"',\n \"font-family\": '\"Arial\"',\n \"font-size\": \"10\",\n \"font-style\": \"normal\",\n \"font-weight\": 400,\n gradient: 0,\n height: 0,\n href: \"http://raphaeljs.com/\",\n \"letter-spacing\": 0,\n opacity: 1,\n path: \"M0,0\",\n r: 0,\n rx: 0,\n ry: 0,\n src: \"\",\n stroke: \"#000\",\n \"stroke-dasharray\": \"\",\n \"stroke-linecap\": \"butt\",\n \"stroke-linejoin\": \"butt\",\n \"stroke-miterlimit\": 0,\n \"stroke-opacity\": 1,\n \"stroke-width\": 1,\n \"stroke-scale\": false, // FreeGroup: draw2d enhancement\n target: \"_blank\",\n \"text-anchor\": \"middle\",\n title: \"Raphael\",\n transform: \"\",\n width: 0,\n x: 0,\n y: 0\n },\n availableAnimAttrs = R._availableAnimAttrs = {\n blur: nu,\n \"clip-rect\": \"csv\",\n cx: nu,\n cy: nu,\n fill: \"colour\",\n \"fill-opacity\": nu,\n \"font-size\": nu,\n height: nu,\n opacity: nu,\n path: \"path\",\n r: nu,\n rx: nu,\n ry: nu,\n stroke: \"colour\",\n \"stroke-opacity\": nu,\n \"stroke-width\": nu,\n transform: \"transform\",\n width: nu,\n x: nu,\n y: nu\n },\n whitespace = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]/g,\n commaSpaces = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/,\n hsrg = {hs: 1, rg: 1},\n p2s = /,?([achlmqrstvxz]),?/gi,\n pathCommand = /([achlmrqstvz])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n tCommand = /([rstm])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n pathValues = /(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/ig,\n radial_gradient = R._radial_gradient = /^r(?:\\(([^,]+?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*([^\\)]+?)\\))?/,\n eldata = {},\n sortByKey = function (a, b) {\n return a.key - b.key;\n },\n sortByNumber = function (a, b) {\n return toFloat(a) - toFloat(b);\n },\n fun = function () {},\n pipe = function (x) {\n return x;\n },\n rectPath = R._rectPath = function (x, y, w, h, r) {\n if (r) {\n return [[\"M\", x + r, y], [\"l\", w - r * 2, 0], [\"a\", r, r, 0, 0, 1, r, r], [\"l\", 0, h - r * 2], [\"a\", r, r, 0, 0, 1, -r, r], [\"l\", r * 2 - w, 0], [\"a\", r, r, 0, 0, 1, -r, -r], [\"l\", 0, r * 2 - h], [\"a\", r, r, 0, 0, 1, r, -r], [\"z\"]];\n }\n return [[\"M\", x, y], [\"l\", w, 0], [\"l\", 0, h], [\"l\", -w, 0], [\"z\"]];\n },\n ellipsePath = function (x, y, rx, ry) {\n if (ry == null) {\n ry = rx;\n }\n return [[\"M\", x, y], [\"m\", 0, -ry], [\"a\", rx, ry, 0, 1, 1, 0, 2 * ry], [\"a\", rx, ry, 0, 1, 1, 0, -2 * ry], [\"z\"]];\n },\n getPath = R._getPath = {\n path: function (el) {\n return el.attr(\"path\");\n },\n circle: function (el) {\n var a = el.attrs;\n return ellipsePath(a.cx, a.cy, a.r);\n },\n ellipse: function (el) {\n var a = el.attrs;\n return ellipsePath(a.cx, a.cy, a.rx, a.ry);\n },\n rect: function (el) {\n var a = el.attrs;\n return rectPath(a.x, a.y, a.width, a.height, a.r);\n },\n image: function (el) {\n var a = el.attrs;\n return rectPath(a.x, a.y, a.width, a.height);\n },\n text: function (el) {\n var bbox = el._getBBox();\n return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);\n },\n set : function(el) {\n var bbox = el._getBBox();\n return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);\n }\n },\n /*\\\n * Raphael.mapPath\n [ method ]\n **\n * Transform the path string with given matrix.\n > Parameters\n - path (string) path string\n - matrix (object) see @Matrix\n = (string) transformed path string\n \\*/\n mapPath = R.mapPath = function (path, matrix) {\n if (!matrix) {\n return path;\n }\n var x, y, i, j, ii, jj, pathi;\n path = path2curve(path);\n for (i = 0, ii = path.length; i < ii; i++) {\n pathi = path[i];\n for (j = 1, jj = pathi.length; j < jj; j += 2) {\n x = matrix.x(pathi[j], pathi[j + 1]);\n y = matrix.y(pathi[j], pathi[j + 1]);\n pathi[j] = x;\n pathi[j + 1] = y;\n }\n }\n return path;\n };\n\n R._g = g;\n /*\\\n * Raphael.type\n [ property (string) ]\n **\n * Can be “SVGâ€, “VML†or empty, depending on browser support.\n \\*/\n R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\", \"1.1\") ? \"SVG\" : \"VML\");\n if (R.type == \"VML\") {\n var d = g.doc.createElement(\"div\"),\n b;\n d.innerHTML = '';\n b = d.firstChild;\n b.style.behavior = \"url(#default#VML)\";\n if (!(b && typeof b.adj == \"object\")) {\n return (R.type = E);\n }\n d = null;\n }\n /*\\\n * Raphael.svg\n [ property (boolean) ]\n **\n * `true` if browser supports SVG.\n \\*/\n /*\\\n * Raphael.vml\n [ property (boolean) ]\n **\n * `true` if browser supports VML.\n \\*/\n R.svg = !(R.vml = R.type == \"VML\");\n R._Paper = Paper;\n /*\\\n * Raphael.fn\n [ property (object) ]\n **\n * You can add your own method to the canvas. For example if you want to draw a pie chart,\n * you can create your own pie chart function and ship it as a Raphaël plugin. To do this\n * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a\n * Raphaël instance is created, otherwise it will take no effect. Please note that the\n * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to\n * ensure any namespacing ensures proper context.\n > Usage\n | Raphael.fn.arrow = function (x1, y1, x2, y2, size) {\n | return this.path( ... );\n | };\n | // or create namespace\n | Raphael.fn.mystuff = {\n | arrow: function () {…},\n | star: function () {…},\n | // etc…\n | };\n | var paper = Raphael(10, 10, 630, 480);\n | // then use it\n | paper.arrow(10, 10, 30, 30, 5).attr({fill: \"#f00\"});\n | paper.mystuff.arrow();\n | paper.mystuff.star();\n \\*/\n R.fn = paperproto = Paper.prototype = R.prototype;\n R._id = 0;\n R._oid = 0;\n /*\\\n * Raphael.is\n [ method ]\n **\n * Handful of replacements for `typeof` operator.\n > Parameters\n - o (…) any object or primitive\n - type (string) name of the type, i.e. “stringâ€, “functionâ€, “numberâ€, etc.\n = (boolean) is given value is of given type\n \\*/\n R.is = function (o, type) {\n type = lowerCase.call(type);\n if (type == \"finite\") {\n return !isnan[has](+o);\n }\n if (type == \"array\") {\n return o instanceof Array;\n }\n return (type == \"null\" && o === null) ||\n (type == typeof o && o !== null) ||\n (type == \"object\" && o === Object(o)) ||\n (type == \"array\" && Array.isArray && Array.isArray(o)) ||\n objectToString.call(o).slice(8, -1).toLowerCase() == type;\n };\n\n function clone(obj) {\n if (typeof obj == \"function\" || Object(obj) !== obj) {\n return obj;\n }\n var res = new obj.constructor;\n for (var key in obj) if (obj[has](key)) {\n res[key] = clone(obj[key]);\n }\n return res;\n }\n\n /*\\\n * Raphael.angle\n [ method ]\n **\n * Returns angle between two or three points\n > Parameters\n - x1 (number) x coord of first point\n - y1 (number) y coord of first point\n - x2 (number) x coord of second point\n - y2 (number) y coord of second point\n - x3 (number) #optional x coord of third point\n - y3 (number) #optional y coord of third point\n = (number) angle in degrees.\n \\*/\n R.angle = function (x1, y1, x2, y2, x3, y3) {\n if (x3 == null) {\n var x = x1 - x2,\n y = y1 - y2;\n if (!x && !y) {\n return 0;\n }\n return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;\n } else {\n return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);\n }\n };\n /*\\\n * Raphael.rad\n [ method ]\n **\n * Transform angle to radians\n > Parameters\n - deg (number) angle in degrees\n = (number) angle in radians.\n \\*/\n R.rad = function (deg) {\n return deg % 360 * PI / 180;\n };\n /*\\\n * Raphael.deg\n [ method ]\n **\n * Transform angle to degrees\n > Parameters\n - rad (number) angle in radians\n = (number) angle in degrees.\n \\*/\n R.deg = function (rad) {\n return Math.round ((rad * 180 / PI% 360)* 1000) / 1000;\n };\n /*\\\n * Raphael.snapTo\n [ method ]\n **\n * Snaps given value to given grid.\n > Parameters\n - values (array|number) given array of values or step of the grid\n - value (number) value to adjust\n - tolerance (number) #optional tolerance for snapping. Default is `10`.\n = (number) adjusted value.\n \\*/\n R.snapTo = function (values, value, tolerance) {\n tolerance = R.is(tolerance, \"finite\") ? tolerance : 10;\n if (R.is(values, array)) {\n var i = values.length;\n while (i--) if (abs(values[i] - value) <= tolerance) {\n return values[i];\n }\n } else {\n values = +values;\n var rem = value % values;\n if (rem < tolerance) {\n return value - rem;\n }\n if (rem > values - tolerance) {\n return value - rem + values;\n }\n }\n return value;\n };\n\n /*\\\n * Raphael.createUUID\n [ method ]\n **\n * Returns RFC4122, version 4 ID\n \\*/\n var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {\n return function () {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(uuidRegEx, uuidReplacer).toUpperCase();\n };\n })(/[xy]/g, function (c) {\n var r = math.random() * 16 | 0,\n v = c == \"x\" ? r : (r & 3 | 8);\n return v.toString(16);\n });\n\n /*\\\n * Raphael.setWindow\n [ method ]\n **\n * Used when you need to draw in `<iframe>`. Switched window to the iframe one.\n > Parameters\n - newwin (window) new window object\n \\*/\n R.setWindow = function (newwin) {\n eve(\"raphael.setWindow\", R, g.win, newwin);\n g.win = newwin;\n g.doc = g.win.document;\n if (R._engine.initWin) {\n R._engine.initWin(g.win);\n }\n };\n var toHex = function (color) {\n if (R.vml) {\n // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/\n var trim = /^\\s+|\\s+$/g;\n var bod;\n try {\n var docum = new ActiveXObject(\"htmlfile\");\n docum.write(\"\");\n docum.close();\n bod = docum.body;\n } catch(e) {\n bod = createPopup().document.body;\n }\n var range = bod.createTextRange();\n toHex = cacher(function (color) {\n try {\n bod.style.color = Str(color).replace(trim, E);\n var value = range.queryCommandValue(\"ForeColor\");\n value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);\n return \"#\" + (\"000000\" + value.toString(16)).slice(-6);\n } catch(e) {\n return \"none\";\n }\n });\n } else {\n var i = g.doc.createElement(\"i\");\n i.title = \"Rapha\\xebl Colour Picker\";\n i.style.display = \"none\";\n g.doc.body.appendChild(i);\n toHex = cacher(function (color) {\n i.style.color = color;\n return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue(\"color\");\n });\n }\n return toHex(color);\n },\n hsbtoString = function () {\n return \"hsb(\" + [this.h, this.s, this.b] + \")\";\n },\n hsltoString = function () {\n return \"hsl(\" + [this.h, this.s, this.l] + \")\";\n },\n rgbtoString = function () {\n return this.hex;\n },\n prepareRGB = function (r, g, b) {\n if (g == null && R.is(r, \"object\") && \"r\" in r && \"g\" in r && \"b\" in r) {\n b = r.b;\n g = r.g;\n r = r.r;\n }\n if (g == null && R.is(r, string)) {\n var clr = R.getRGB(r);\n r = clr.r;\n g = clr.g;\n b = clr.b;\n }\n if (r > 1 || g > 1 || b > 1) {\n r /= 255;\n g /= 255;\n b /= 255;\n }\n\n return [r, g, b];\n },\n packageRGB = function (r, g, b, o) {\n r *= 255;\n g *= 255;\n b *= 255;\n var rgb = {\n r: r,\n g: g,\n b: b,\n hex: R.rgb(r, g, b),\n toString: rgbtoString\n };\n R.is(o, \"finite\") && (rgb.opacity = o);\n return rgb;\n };\n\n /*\\\n * Raphael.color\n [ method ]\n **\n * Parses the color string and returns object with all values for the given color.\n > Parameters\n - clr (string) color string in one of the supported formats (see @Raphael.getRGB)\n = (object) Combined RGB & HSB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue,\n o hex (string) color in HTML/CSS format: #••••••,\n o error (boolean) `true` if string can’t be parsed,\n o h (number) hue,\n o s (number) saturation,\n o v (number) value (brightness),\n o l (number) lightness\n o }\n \\*/\n R.color = function (clr) {\n var rgb;\n if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"b\" in clr) {\n rgb = R.hsb2rgb(clr);\n clr.r = rgb.r;\n clr.g = rgb.g;\n clr.b = rgb.b;\n clr.hex = rgb.hex;\n } else if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"l\" in clr) {\n rgb = R.hsl2rgb(clr);\n clr.r = rgb.r;\n clr.g = rgb.g;\n clr.b = rgb.b;\n clr.hex = rgb.hex;\n } else {\n if (R.is(clr, \"string\")) {\n clr = R.getRGB(clr);\n }\n if (R.is(clr, \"object\") && \"r\" in clr && \"g\" in clr && \"b\" in clr) {\n rgb = R.rgb2hsl(clr);\n clr.h = rgb.h;\n clr.s = rgb.s;\n clr.l = rgb.l;\n rgb = R.rgb2hsb(clr);\n clr.v = rgb.b;\n } else {\n clr = {hex: \"none\"};\n clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;\n }\n }\n clr.toString = rgbtoString;\n return clr;\n };\n /*\\\n * Raphael.hsb2rgb\n [ method ]\n **\n * Converts HSB values to RGB object.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - v (number) value or brightness\n = (object) RGB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue,\n o hex (string) color in HTML/CSS format: #••••••\n o }\n \\*/\n R.hsb2rgb = function (h, s, v, o) {\n if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"b\" in h) {\n v = h.b;\n s = h.s;\n o = h.o;\n h = h.h;\n }\n h *= 360;\n var R, G, B, X, C;\n h = (h % 360) / 60;\n C = v * s;\n X = C * (1 - abs(h % 2 - 1));\n R = G = B = v - C;\n\n h = ~~h;\n R += [C, X, 0, 0, X, C][h];\n G += [X, C, C, X, 0, 0][h];\n B += [0, 0, X, C, C, X][h];\n return packageRGB(R, G, B, o);\n };\n /*\\\n * Raphael.hsl2rgb\n [ method ]\n **\n * Converts HSL values to RGB object.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - l (number) luminosity\n = (object) RGB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue,\n o hex (string) color in HTML/CSS format: #••••••\n o }\n \\*/\n R.hsl2rgb = function (h, s, l, o) {\n if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"l\" in h) {\n l = h.l;\n s = h.s;\n h = h.h;\n }\n if (h > 1 || s > 1 || l > 1) {\n h /= 360;\n s /= 100;\n l /= 100;\n }\n h *= 360;\n var R, G, B, X, C;\n h = (h % 360) / 60;\n C = 2 * s * (l < .5 ? l : 1 - l);\n X = C * (1 - abs(h % 2 - 1));\n R = G = B = l - C / 2;\n\n h = ~~h;\n R += [C, X, 0, 0, X, C][h];\n G += [X, C, C, X, 0, 0][h];\n B += [0, 0, X, C, C, X][h];\n return packageRGB(R, G, B, o);\n };\n /*\\\n * Raphael.rgb2hsb\n [ method ]\n **\n * Converts RGB values to HSB object.\n > Parameters\n - r (number) red\n - g (number) green\n - b (number) blue\n = (object) HSB object in format:\n o {\n o h (number) hue\n o s (number) saturation\n o b (number) brightness\n o }\n \\*/\n R.rgb2hsb = function (r, g, b) {\n b = prepareRGB(r, g, b);\n r = b[0];\n g = b[1];\n b = b[2];\n\n var H, S, V, C;\n V = mmax(r, g, b);\n C = V - mmin(r, g, b);\n H = (C == 0 ? null :\n V == r ? (g - b) / C :\n V == g ? (b - r) / C + 2 :\n (r - g) / C + 4\n );\n H = ((H + 360) % 6) * 60 / 360;\n S = C == 0 ? 0 : C / V;\n return {h: H, s: S, b: V, toString: hsbtoString};\n };\n /*\\\n * Raphael.rgb2hsl\n [ method ]\n **\n * Converts RGB values to HSL object.\n > Parameters\n - r (number) red\n - g (number) green\n - b (number) blue\n = (object) HSL object in format:\n o {\n o h (number) hue\n o s (number) saturation\n o l (number) luminosity\n o }\n \\*/\n R.rgb2hsl = function (r, g, b) {\n b = prepareRGB(r, g, b);\n r = b[0];\n g = b[1];\n b = b[2];\n\n var H, S, L, M, m, C;\n M = mmax(r, g, b);\n m = mmin(r, g, b);\n C = M - m;\n H = (C == 0 ? null :\n M == r ? (g - b) / C :\n M == g ? (b - r) / C + 2 :\n (r - g) / C + 4);\n H = ((H + 360) % 6) * 60 / 360;\n L = (M + m) / 2;\n S = (C == 0 ? 0 :\n L < .5 ? C / (2 * L) :\n C / (2 - 2 * L));\n return {h: H, s: S, l: L, toString: hsltoString};\n };\n R._path2string = function () {\n return this.join(\",\").replace(p2s, \"$1\");\n };\n function repush(array, item) {\n for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {\n return array.push(array.splice(i, 1)[0]);\n }\n }\n function cacher(f, scope, postprocessor) {\n function newf() {\n var arg = Array.prototype.slice.call(arguments, 0),\n args = arg.join(\"\\u2400\"),\n cache = newf.cache = newf.cache || {},\n count = newf.count = newf.count || [];\n if (cache[has](args)) {\n repush(count, args);\n return postprocessor ? postprocessor(cache[args]) : cache[args];\n }\n count.length >= 1e3 && delete cache[count.shift()];\n count.push(args);\n cache[args] = f[apply](scope, arg);\n return postprocessor ? postprocessor(cache[args]) : cache[args];\n }\n return newf;\n }\n\n var preload = R._preload = function (src, f) {\n var img = g.doc.createElement(\"img\");\n img.style.cssText = \"position:absolute;left:-9999em;top:-9999em\";\n img.onload = function () {\n f.call(this);\n this.onload = null;\n g.doc.body.removeChild(this);\n };\n img.onerror = function () {\n g.doc.body.removeChild(this);\n };\n g.doc.body.appendChild(img);\n img.src = src;\n };\n\n function clrToString() {\n return this.hex;\n }\n\n /*\\\n * Raphael.getRGB\n [ method ]\n **\n * Parses colour string as RGB object\n > Parameters\n - colour (string) colour string in one of formats:\n # \n # Colour name (“red
â€, “green
â€, “cornflowerblue
â€, etc) \n # #••• — shortened HTML colour: (“#000
â€, “#fc0
â€, etc) \n # #•••••• — full length HTML colour: (“#000000
â€, “#bd2300
â€) \n # rgb(•••, •••, •••) — red, green and blue channels’ values: (“rgb(200, 100, 0)
â€) \n # rgb(•••%, •••%, •••%) — same as above, but in %: (“rgb(100%, 175%, 0%)
â€) \n # hsb(•••, •••, •••) — hue, saturation and brightness values: (“hsb(0.5, 0.25, 1)
â€) \n # hsb(•••%, •••%, •••%) — same as above, but in % \n # hsl(•••, •••, •••) — same as hsb \n # hsl(•••%, •••%, •••%) — same as hsb \n # \n = (object) RGB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue\n o hex (string) color in HTML/CSS format: #••••••,\n o error (boolean) true if string can’t be parsed\n o }\n \\*/\n R.getRGB = cacher(function (colour) {\n if (!colour || !!((colour = Str(colour)).indexOf(\"-\") + 1)) {\n return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n }\n if (colour == \"none\") {\n return {r: -1, g: -1, b: -1, hex: \"none\", toString: clrToString};\n }\n !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == \"#\") && (colour = toHex(colour));\n var res,\n red,\n green,\n blue,\n opacity,\n t,\n values,\n rgb = colour.match(colourRegExp);\n if (rgb) {\n if (rgb[2]) {\n blue = toInt(rgb[2].substring(5), 16);\n green = toInt(rgb[2].substring(3, 5), 16);\n red = toInt(rgb[2].substring(1, 3), 16);\n }\n if (rgb[3]) {\n blue = toInt((t = rgb[3].charAt(3)) + t, 16);\n green = toInt((t = rgb[3].charAt(2)) + t, 16);\n red = toInt((t = rgb[3].charAt(1)) + t, 16);\n }\n if (rgb[4]) {\n values = rgb[4][split](commaSpaces);\n red = toFloat(values[0]);\n values[0].slice(-1) == \"%\" && (red *= 2.55);\n green = toFloat(values[1]);\n values[1].slice(-1) == \"%\" && (green *= 2.55);\n blue = toFloat(values[2]);\n values[2].slice(-1) == \"%\" && (blue *= 2.55);\n rgb[1].toLowerCase().slice(0, 4) == \"rgba\" && (opacity = toFloat(values[3]));\n values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n }\n if (rgb[5]) {\n values = rgb[5][split](commaSpaces);\n red = toFloat(values[0]);\n values[0].slice(-1) == \"%\" && (red *= 2.55);\n green = toFloat(values[1]);\n values[1].slice(-1) == \"%\" && (green *= 2.55);\n blue = toFloat(values[2]);\n values[2].slice(-1) == \"%\" && (blue *= 2.55);\n (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n rgb[1].toLowerCase().slice(0, 4) == \"hsba\" && (opacity = toFloat(values[3]));\n values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n return R.hsb2rgb(red, green, blue, opacity);\n }\n if (rgb[6]) {\n values = rgb[6][split](commaSpaces);\n red = toFloat(values[0]);\n values[0].slice(-1) == \"%\" && (red *= 2.55);\n green = toFloat(values[1]);\n values[1].slice(-1) == \"%\" && (green *= 2.55);\n blue = toFloat(values[2]);\n values[2].slice(-1) == \"%\" && (blue *= 2.55);\n (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n rgb[1].toLowerCase().slice(0, 4) == \"hsla\" && (opacity = toFloat(values[3]));\n values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n return R.hsl2rgb(red, green, blue, opacity);\n }\n rgb = {r: red, g: green, b: blue, toString: clrToString};\n rgb.hex = \"#\" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);\n R.is(opacity, \"finite\") && (rgb.opacity = opacity);\n return rgb;\n }\n return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n }, R);\n /*\\\n * Raphael.hsb\n [ method ]\n **\n * Converts HSB values to hex representation of the colour.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - b (number) value or brightness\n = (string) hex representation of the colour.\n \\*/\n R.hsb = cacher(function (h, s, b) {\n return R.hsb2rgb(h, s, b).hex;\n });\n /*\\\n * Raphael.hsl\n [ method ]\n **\n * Converts HSL values to hex representation of the colour.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - l (number) luminosity\n = (string) hex representation of the colour.\n \\*/\n R.hsl = cacher(function (h, s, l) {\n return R.hsl2rgb(h, s, l).hex;\n });\n /*\\\n * Raphael.rgb\n [ method ]\n **\n * Converts RGB values to hex representation of the colour.\n > Parameters\n - r (number) red\n - g (number) green\n - b (number) blue\n = (string) hex representation of the colour.\n \\*/\n R.rgb = cacher(function (r, g, b) {\n function round(x) { return (x + 0.5) | 0; }\n return \"#\" + (16777216 | round(b) | (round(g) << 8) | (round(r) << 16)).toString(16).slice(1);\n });\n /*\\\n * Raphael.getColor\n [ method ]\n **\n * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset\n > Parameters\n - value (number) #optional brightness, default is `0.75`\n = (string) hex representation of the colour.\n \\*/\n R.getColor = function (value) {\n var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},\n rgb = this.hsb2rgb(start.h, start.s, start.b);\n start.h += .075;\n if (start.h > 1) {\n start.h = 0;\n start.s -= .2;\n start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});\n }\n return rgb.hex;\n };\n /*\\\n * Raphael.getColor.reset\n [ method ]\n **\n * Resets spectrum position for @Raphael.getColor back to red.\n \\*/\n R.getColor.reset = function () {\n delete this.start;\n };\n\n // http://schepers.cc/getting-to-the-point\n function catmullRom2bezier(crp, z) {\n var d = [];\n for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {\n var p = [\n {x: +crp[i - 2], y: +crp[i - 1]},\n {x: +crp[i], y: +crp[i + 1]},\n {x: +crp[i + 2], y: +crp[i + 3]},\n {x: +crp[i + 4], y: +crp[i + 5]}\n ];\n if (z) {\n if (!i) {\n p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};\n } else if (iLen - 4 == i) {\n p[3] = {x: +crp[0], y: +crp[1]};\n } else if (iLen - 2 == i) {\n p[2] = {x: +crp[0], y: +crp[1]};\n p[3] = {x: +crp[2], y: +crp[3]};\n }\n } else {\n if (iLen - 4 == i) {\n p[3] = p[2];\n } else if (!i) {\n p[0] = {x: +crp[i], y: +crp[i + 1]};\n }\n }\n d.push([\"C\",\n (-p[0].x + 6 * p[1].x + p[2].x) / 6,\n (-p[0].y + 6 * p[1].y + p[2].y) / 6,\n (p[1].x + 6 * p[2].x - p[3].x) / 6,\n (p[1].y + 6*p[2].y - p[3].y) / 6,\n p[2].x,\n p[2].y\n ]);\n }\n\n return d;\n }\n /*\\\n * Raphael.parsePathString\n [ method ]\n **\n * Utility method\n **\n * Parses given path string into an array of arrays of path segments.\n > Parameters\n - pathString (string|array) path string or array of segments (in the last case it will be returned straight away)\n = (array) array of segments.\n \\*/\n R.parsePathString = function (pathString) {\n if (!pathString) {\n return null;\n }\n var pth = paths(pathString);\n if (pth.arr) {\n return pathClone(pth.arr);\n }\n\n var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},\n data = [];\n if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption\n data = pathClone(pathString);\n }\n if (!data.length) {\n Str(pathString).replace(pathCommand, function (a, b, c) {\n var params = [],\n name = b.toLowerCase();\n c.replace(pathValues, function (a, b) {\n b && params.push(+b);\n });\n if (name == \"m\" && params.length > 2) {\n data.push([b][concat](params.splice(0, 2)));\n name = \"l\";\n b = b == \"m\" ? \"l\" : \"L\";\n }\n if (name == \"r\") {\n data.push([b][concat](params));\n } else while (params.length >= paramCounts[name]) {\n data.push([b][concat](params.splice(0, paramCounts[name])));\n if (!paramCounts[name]) {\n break;\n }\n }\n });\n }\n data.toString = R._path2string;\n pth.arr = pathClone(data);\n return data;\n };\n /*\\\n * Raphael.parseTransformString\n [ method ]\n **\n * Utility method\n **\n * Parses given path string into an array of transformations.\n > Parameters\n - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)\n = (array) array of transformations.\n \\*/\n R.parseTransformString = cacher(function (TString) {\n if (!TString) {\n return null;\n }\n var paramCounts = {r: 3, s: 4, t: 2, m: 6},\n data = [];\n if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption\n data = pathClone(TString);\n }\n if (!data.length) {\n Str(TString).replace(tCommand, function (a, b, c) {\n var params = [],\n name = lowerCase.call(b);\n c.replace(pathValues, function (a, b) {\n b && params.push(+b);\n });\n data.push([b][concat](params));\n });\n }\n data.toString = R._path2string;\n return data;\n });\n // PATHS\n var paths = function (ps) {\n var p = paths.ps = paths.ps || {};\n if (p[ps]) {\n p[ps].sleep = 100;\n } else {\n p[ps] = {\n sleep: 100\n };\n }\n setTimeout(function () {\n for (var key in p) if (p[has](key) && key != ps) {\n p[key].sleep--;\n !p[key].sleep && delete p[key];\n }\n });\n return p[ps];\n };\n /*\\\n * Raphael.findDotsAtSegment\n [ method ]\n **\n * Utility method\n **\n * Find dot coordinates on the given cubic bezier curve at the given t.\n > Parameters\n - p1x (number) x of the first point of the curve\n - p1y (number) y of the first point of the curve\n - c1x (number) x of the first anchor of the curve\n - c1y (number) y of the first anchor of the curve\n - c2x (number) x of the second anchor of the curve\n - c2y (number) y of the second anchor of the curve\n - p2x (number) x of the second point of the curve\n - p2y (number) y of the second point of the curve\n - t (number) position on the curve (0..1)\n = (object) point information in format:\n o {\n o x: (number) x coordinate of the point\n o y: (number) y coordinate of the point\n o m: {\n o x: (number) x coordinate of the left anchor\n o y: (number) y coordinate of the left anchor\n o }\n o n: {\n o x: (number) x coordinate of the right anchor\n o y: (number) y coordinate of the right anchor\n o }\n o start: {\n o x: (number) x coordinate of the start of the curve\n o y: (number) y coordinate of the start of the curve\n o }\n o end: {\n o x: (number) x coordinate of the end of the curve\n o y: (number) y coordinate of the end of the curve\n o }\n o alpha: (number) angle of the curve derivative at the point\n o }\n \\*/\n R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n var t1 = 1 - t,\n t13 = pow(t1, 3),\n t12 = pow(t1, 2),\n t2 = t * t,\n t3 = t2 * t,\n x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,\n y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,\n mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),\n my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),\n nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),\n ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),\n ax = t1 * p1x + t * c1x,\n ay = t1 * p1y + t * c1y,\n cx = t1 * c2x + t * p2x,\n cy = t1 * c2y + t * p2y,\n alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);\n (mx > nx || my < ny) && (alpha += 180);\n return {\n x: x,\n y: y,\n m: {x: mx, y: my},\n n: {x: nx, y: ny},\n start: {x: ax, y: ay},\n end: {x: cx, y: cy},\n alpha: alpha\n };\n };\n /*\\\n * Raphael.bezierBBox\n [ method ]\n **\n * Utility method\n **\n * Return bounding box of a given cubic bezier curve\n > Parameters\n - p1x (number) x of the first point of the curve\n - p1y (number) y of the first point of the curve\n - c1x (number) x of the first anchor of the curve\n - c1y (number) y of the first anchor of the curve\n - c2x (number) x of the second anchor of the curve\n - c2y (number) y of the second anchor of the curve\n - p2x (number) x of the second point of the curve\n - p2y (number) y of the second point of the curve\n * or\n - bez (array) array of six points for bezier curve\n = (object) point information in format:\n o {\n o min: {\n o x: (number) x coordinate of the left point\n o y: (number) y coordinate of the top point\n o }\n o max: {\n o x: (number) x coordinate of the right point\n o y: (number) y coordinate of the bottom point\n o }\n o }\n \\*/\n R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n if (!R.is(p1x, \"array\")) {\n p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];\n }\n var bbox = curveDim.apply(null, p1x);\n return {\n x: bbox.min.x,\n y: bbox.min.y,\n x2: bbox.max.x,\n y2: bbox.max.y,\n width: bbox.max.x - bbox.min.x,\n height: bbox.max.y - bbox.min.y\n };\n };\n /*\\\n * Raphael.isPointInsideBBox\n [ method ]\n **\n * Utility method\n **\n * Returns `true` if given point is inside bounding boxes.\n > Parameters\n - bbox (string) bounding box\n - x (string) x coordinate of the point\n - y (string) y coordinate of the point\n = (boolean) `true` if point inside\n \\*/\n R.isPointInsideBBox = function (bbox, x, y) {\n return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;\n };\n /*\\\n * Raphael.isBBoxIntersect\n [ method ]\n **\n * Utility method\n **\n * Returns `true` if two bounding boxes intersect\n > Parameters\n - bbox1 (string) first bounding box\n - bbox2 (string) second bounding box\n = (boolean) `true` if they intersect\n \\*/\n R.isBBoxIntersect = function (bbox1, bbox2) {\n var i = R.isPointInsideBBox;\n return i(bbox2, bbox1.x, bbox1.y)\n || i(bbox2, bbox1.x2, bbox1.y)\n || i(bbox2, bbox1.x, bbox1.y2)\n || i(bbox2, bbox1.x2, bbox1.y2)\n || i(bbox1, bbox2.x, bbox2.y)\n || i(bbox1, bbox2.x2, bbox2.y)\n || i(bbox1, bbox2.x, bbox2.y2)\n || i(bbox1, bbox2.x2, bbox2.y2)\n || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)\n && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);\n };\n function base3(t, p1, p2, p3, p4) {\n var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,\n t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;\n return t * t2 - 3 * p1 + 3 * p2;\n }\n function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {\n if (z == null) {\n z = 1;\n }\n z = z > 1 ? 1 : z < 0 ? 0 : z;\n var z2 = z / 2,\n n = 12,\n Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],\n Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],\n sum = 0;\n for (var i = 0; i < n; i++) {\n var ct = z2 * Tvalues[i] + z2,\n xbase = base3(ct, x1, x2, x3, x4),\n ybase = base3(ct, y1, y2, y3, y4),\n comb = xbase * xbase + ybase * ybase;\n sum += Cvalues[i] * math.sqrt(comb);\n }\n return z2 * sum;\n }\n function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {\n if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {\n return;\n }\n var t = 1,\n step = t / 2,\n t2 = t - step,\n l,\n e = .01;\n l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n while (abs(l - ll) > e) {\n step /= 2;\n t2 += (l < ll ? 1 : -1) * step;\n l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n }\n return t2;\n }\n function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {\n if (\n mmax(x1, x2) < mmin(x3, x4) ||\n mmin(x1, x2) > mmax(x3, x4) ||\n mmax(y1, y2) < mmin(y3, y4) ||\n mmin(y1, y2) > mmax(y3, y4)\n ) {\n return;\n }\n var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),\n ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),\n denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);\n\n if (!denominator) {\n return;\n }\n var px = nx / denominator,\n py = ny / denominator,\n px2 = +px.toFixed(2),\n py2 = +py.toFixed(2);\n if (\n px2 < +mmin(x1, x2).toFixed(2) ||\n px2 > +mmax(x1, x2).toFixed(2) ||\n px2 < +mmin(x3, x4).toFixed(2) ||\n px2 > +mmax(x3, x4).toFixed(2) ||\n py2 < +mmin(y1, y2).toFixed(2) ||\n py2 > +mmax(y1, y2).toFixed(2) ||\n py2 < +mmin(y3, y4).toFixed(2) ||\n py2 > +mmax(y3, y4).toFixed(2)\n ) {\n return;\n }\n return {x: px, y: py};\n }\n function inter(bez1, bez2) {\n return interHelper(bez1, bez2);\n }\n function interCount(bez1, bez2) {\n return interHelper(bez1, bez2, 1);\n }\n function interHelper(bez1, bez2, justCount) {\n var bbox1 = R.bezierBBox(bez1),\n bbox2 = R.bezierBBox(bez2);\n if (!R.isBBoxIntersect(bbox1, bbox2)) {\n return justCount ? 0 : [];\n }\n var l1 = bezlen.apply(0, bez1),\n l2 = bezlen.apply(0, bez2),\n n1 = mmax(~~(l1 / 5), 1),\n n2 = mmax(~~(l2 / 5), 1),\n dots1 = [],\n dots2 = [],\n xy = {},\n res = justCount ? 0 : [];\n for (var i = 0; i < n1 + 1; i++) {\n var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));\n dots1.push({x: p.x, y: p.y, t: i / n1});\n }\n for (i = 0; i < n2 + 1; i++) {\n p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));\n dots2.push({x: p.x, y: p.y, t: i / n2});\n }\n for (i = 0; i < n1; i++) {\n for (var j = 0; j < n2; j++) {\n var di = dots1[i],\n di1 = dots1[i + 1],\n dj = dots2[j],\n dj1 = dots2[j + 1],\n ci = abs(di1.x - di.x) < .001 ? \"y\" : \"x\",\n cj = abs(dj1.x - dj.x) < .001 ? \"y\" : \"x\",\n is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);\n if (is) {\n if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {\n continue;\n }\n xy[is.x.toFixed(4)] = is.y.toFixed(4);\n var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),\n t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);\n if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) {\n if (justCount) {\n res++;\n } else {\n res.push({\n x: is.x,\n y: is.y,\n t1: mmin(t1, 1),\n t2: mmin(t2, 1)\n });\n }\n }\n }\n }\n }\n return res;\n }\n /*\\\n * Raphael.pathIntersection\n [ method ]\n **\n * Utility method\n **\n * Finds intersections of two paths\n > Parameters\n - path1 (string) path string\n - path2 (string) path string\n = (array) dots of intersection\n o [\n o {\n o x: (number) x coordinate of the point\n o y: (number) y coordinate of the point\n o t1: (number) t value for segment of path1\n o t2: (number) t value for segment of path2\n o segment1: (number) order number for segment of path1\n o segment2: (number) order number for segment of path2\n o bez1: (array) eight coordinates representing beziér curve for the segment of path1\n o bez2: (array) eight coordinates representing beziér curve for the segment of path2\n o }\n o ]\n \\*/\n R.pathIntersection = function (path1, path2) {\n return interPathHelper(path1, path2);\n };\n R.pathIntersectionNumber = function (path1, path2) {\n return interPathHelper(path1, path2, 1);\n };\n function interPathHelper(path1, path2, justCount) {\n path1 = R._path2curve(path1);\n path2 = R._path2curve(path2);\n var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,\n res = justCount ? 0 : [];\n for (var i = 0, ii = path1.length; i < ii; i++) {\n var pi = path1[i];\n if (pi[0] == \"M\") {\n x1 = x1m = pi[1];\n y1 = y1m = pi[2];\n } else {\n if (pi[0] == \"C\") {\n bez1 = [x1, y1].concat(pi.slice(1));\n x1 = bez1[6];\n y1 = bez1[7];\n } else {\n bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];\n x1 = x1m;\n y1 = y1m;\n }\n for (var j = 0, jj = path2.length; j < jj; j++) {\n var pj = path2[j];\n if (pj[0] == \"M\") {\n x2 = x2m = pj[1];\n y2 = y2m = pj[2];\n } else {\n if (pj[0] == \"C\") {\n bez2 = [x2, y2].concat(pj.slice(1));\n x2 = bez2[6];\n y2 = bez2[7];\n } else {\n bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];\n x2 = x2m;\n y2 = y2m;\n }\n var intr = interHelper(bez1, bez2, justCount);\n if (justCount) {\n res += intr;\n } else {\n for (var k = 0, kk = intr.length; k < kk; k++) {\n intr[k].segment1 = i;\n intr[k].segment2 = j;\n intr[k].bez1 = bez1;\n intr[k].bez2 = bez2;\n }\n res = res.concat(intr);\n }\n }\n }\n }\n }\n return res;\n }\n /*\\\n * Raphael.isPointInsidePath\n [ method ]\n **\n * Utility method\n **\n * Returns `true` if given point is inside a given closed path.\n > Parameters\n - path (string) path string\n - x (number) x of the point\n - y (number) y of the point\n = (boolean) true, if point is inside the path\n \\*/\n R.isPointInsidePath = function (path, x, y) {\n var bbox = R.pathBBox(path);\n return R.isPointInsideBBox(bbox, x, y) &&\n interPathHelper(path, [[\"M\", x, y], [\"H\", bbox.x2 + 10]], 1) % 2 == 1;\n };\n R._removedFactory = function (methodname) {\n return function () {\n eve(\"raphael.log\", null, \"Rapha\\xebl: you are calling to method \\u201c\" + methodname + \"\\u201d of removed object\", methodname);\n };\n };\n /*\\\n * Raphael.pathBBox\n [ method ]\n **\n * Utility method\n **\n * Return bounding box of a given path\n > Parameters\n - path (string) path string\n = (object) bounding box\n o {\n o x: (number) x coordinate of the left top point of the box\n o y: (number) y coordinate of the left top point of the box\n o x2: (number) x coordinate of the right bottom point of the box\n o y2: (number) y coordinate of the right bottom point of the box\n o width: (number) width of the box\n o height: (number) height of the box\n o cx: (number) x coordinate of the center of the box\n o cy: (number) y coordinate of the center of the box\n o }\n \\*/\n var pathDimensions = R.pathBBox = function (path) {\n var pth = paths(path);\n if (pth.bbox) {\n var b= pth.bbox;\n return {x: b.x, y: b.y, width: b.width, height: b.height, x2: b.x2, y2: b.y2} ; // FREEGROUP FIX!!!!!!\n // raphael reuse the returned bbox. You must clone it here if the caller need the bbxo for\n //further calculation\n }\n if (!path) {\n return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};\n }\n path = path2curve(path);\n var x = 0,\n y = 0,\n X = [],\n Y = [],\n p;\n for (var i = 0, ii = path.length; i < ii; i++) {\n p = path[i];\n if (p[0] == \"M\") {\n x = p[1];\n y = p[2];\n X.push(x);\n Y.push(y);\n } else {\n var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n X = X[concat](dim.min.x, dim.max.x);\n Y = Y[concat](dim.min.y, dim.max.y);\n x = p[5];\n y = p[6];\n }\n }\n var xmin = mmin[apply](0, X),\n ymin = mmin[apply](0, Y),\n xmax = mmax[apply](0, X),\n ymax = mmax[apply](0, Y),\n width = xmax - xmin,\n height = ymax - ymin,\n bb = {\n x: xmin,\n y: ymin,\n x2: xmax,\n y2: ymax,\n width: width,\n height: height,\n cx: xmin + width / 2,\n cy: ymin + height / 2\n };\n pth.bbox = clone(bb);\n return bb;\n },\n pathClone = function (pathArray) {\n var res = clone(pathArray);\n res.toString = R._path2string;\n return res;\n },\n pathToRelative = R._pathToRelative = function (pathArray) {\n var pth = paths(pathArray);\n if (pth.rel) {\n return pathClone(pth.rel);\n }\n if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n pathArray = R.parsePathString(pathArray);\n }\n var res = [],\n x = 0,\n y = 0,\n mx = 0,\n my = 0,\n start = 0;\n if (pathArray[0][0] == \"M\") {\n x = pathArray[0][1];\n y = pathArray[0][2];\n mx = x;\n my = y;\n start++;\n res.push([\"M\", x, y]);\n }\n for (var i = start, ii = pathArray.length; i < ii; i++) {\n var r = res[i] = [],\n pa = pathArray[i];\n if (pa[0] != lowerCase.call(pa[0])) {\n r[0] = lowerCase.call(pa[0]);\n switch (r[0]) {\n case \"a\":\n r[1] = pa[1];\n r[2] = pa[2];\n r[3] = pa[3];\n r[4] = pa[4];\n r[5] = pa[5];\n r[6] = +(pa[6] - x).toFixed(3);\n r[7] = +(pa[7] - y).toFixed(3);\n break;\n case \"v\":\n r[1] = +(pa[1] - y).toFixed(3);\n break;\n case \"m\":\n mx = pa[1];\n my = pa[2];\n default:\n for (var j = 1, jj = pa.length; j < jj; j++) {\n r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);\n }\n }\n } else {\n r = res[i] = [];\n if (pa[0] == \"m\") {\n mx = pa[1] + x;\n my = pa[2] + y;\n }\n for (var k = 0, kk = pa.length; k < kk; k++) {\n res[i][k] = pa[k];\n }\n }\n var len = res[i].length;\n switch (res[i][0]) {\n case \"z\":\n x = mx;\n y = my;\n break;\n case \"h\":\n x += +res[i][len - 1];\n break;\n case \"v\":\n y += +res[i][len - 1];\n break;\n default:\n x += +res[i][len - 2];\n y += +res[i][len - 1];\n }\n }\n res.toString = R._path2string;\n pth.rel = pathClone(res);\n return res;\n },\n pathToAbsolute = R._pathToAbsolute = function (pathArray) {\n var pth = paths(pathArray);\n if (pth.abs) {\n return pathClone(pth.abs);\n }\n if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n pathArray = R.parsePathString(pathArray);\n }\n if (!pathArray || !pathArray.length) {\n return [[\"M\", 0, 0]];\n }\n var res = [],\n x = 0,\n y = 0,\n mx = 0,\n my = 0,\n start = 0;\n if (pathArray[0][0] == \"M\") {\n x = +pathArray[0][1];\n y = +pathArray[0][2];\n mx = x;\n my = y;\n start++;\n res[0] = [\"M\", x, y];\n }\n var crz = pathArray.length == 3 && pathArray[0][0] == \"M\" && pathArray[1][0].toUpperCase() == \"R\" && pathArray[2][0].toUpperCase() == \"Z\";\n for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {\n res.push(r = []);\n pa = pathArray[i];\n if (pa[0] != upperCase.call(pa[0])) {\n r[0] = upperCase.call(pa[0]);\n switch (r[0]) {\n case \"A\":\n r[1] = pa[1];\n r[2] = pa[2];\n r[3] = pa[3];\n r[4] = pa[4];\n r[5] = pa[5];\n r[6] = +(pa[6] + x);\n r[7] = +(pa[7] + y);\n break;\n case \"V\":\n r[1] = +pa[1] + y;\n break;\n case \"H\":\n r[1] = +pa[1] + x;\n break;\n case \"R\":\n var dots = [x, y][concat](pa.slice(1));\n for (var j = 2, jj = dots.length; j < jj; j++) {\n dots[j] = +dots[j] + x;\n dots[++j] = +dots[j] + y;\n }\n res.pop();\n res = res[concat](catmullRom2bezier(dots, crz));\n break;\n case \"M\":\n mx = +pa[1] + x;\n my = +pa[2] + y;\n default:\n for (j = 1, jj = pa.length; j < jj; j++) {\n r[j] = +pa[j] + ((j % 2) ? x : y);\n }\n }\n } else if (pa[0] == \"R\") {\n dots = [x, y][concat](pa.slice(1));\n res.pop();\n res = res[concat](catmullRom2bezier(dots, crz));\n r = [\"R\"][concat](pa.slice(-2));\n } else {\n for (var k = 0, kk = pa.length; k < kk; k++) {\n r[k] = pa[k];\n }\n }\n switch (r[0]) {\n case \"Z\":\n x = mx;\n y = my;\n break;\n case \"H\":\n x = r[1];\n break;\n case \"V\":\n y = r[1];\n break;\n case \"M\":\n mx = r[r.length - 2];\n my = r[r.length - 1];\n default:\n x = r[r.length - 2];\n y = r[r.length - 1];\n }\n }\n res.toString = R._path2string;\n pth.abs = pathClone(res);\n return res;\n },\n l2c = function (x1, y1, x2, y2) {\n return [x1, y1, x2, y2, x2, y2];\n },\n q2c = function (x1, y1, ax, ay, x2, y2) {\n var _13 = 1 / 3,\n _23 = 2 / 3;\n return [\n _13 * x1 + _23 * ax,\n _13 * y1 + _23 * ay,\n _13 * x2 + _23 * ax,\n _13 * y2 + _23 * ay,\n x2,\n y2\n ];\n },\n a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {\n // for more information of where this math came from visit:\n // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes\n var _120 = PI * 120 / 180,\n rad = PI / 180 * (+angle || 0),\n res = [],\n xy,\n rotate = cacher(function (x, y, rad) {\n var X = x * math.cos(rad) - y * math.sin(rad),\n Y = x * math.sin(rad) + y * math.cos(rad);\n return {x: X, y: Y};\n });\n if (!recursive) {\n xy = rotate(x1, y1, -rad);\n x1 = xy.x;\n y1 = xy.y;\n xy = rotate(x2, y2, -rad);\n x2 = xy.x;\n y2 = xy.y;\n var cos = math.cos(PI / 180 * angle),\n sin = math.sin(PI / 180 * angle),\n x = (x1 - x2) / 2,\n y = (y1 - y2) / 2;\n var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);\n if (h > 1) {\n h = math.sqrt(h);\n rx = h * rx;\n ry = h * ry;\n }\n var rx2 = rx * rx,\n ry2 = ry * ry,\n k = (large_arc_flag == sweep_flag ? -1 : 1) *\n math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),\n cx = k * rx * y / ry + (x1 + x2) / 2,\n cy = k * -ry * x / rx + (y1 + y2) / 2,\n f1 = math.asin(((y1 - cy) / ry).toFixed(9)),\n f2 = math.asin(((y2 - cy) / ry).toFixed(9));\n\n f1 = x1 < cx ? PI - f1 : f1;\n f2 = x2 < cx ? PI - f2 : f2;\n f1 < 0 && (f1 = PI * 2 + f1);\n f2 < 0 && (f2 = PI * 2 + f2);\n if (sweep_flag && f1 > f2) {\n f1 = f1 - PI * 2;\n }\n if (!sweep_flag && f2 > f1) {\n f2 = f2 - PI * 2;\n }\n } else {\n f1 = recursive[0];\n f2 = recursive[1];\n cx = recursive[2];\n cy = recursive[3];\n }\n var df = f2 - f1;\n if (abs(df) > _120) {\n var f2old = f2,\n x2old = x2,\n y2old = y2;\n f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);\n x2 = cx + rx * math.cos(f2);\n y2 = cy + ry * math.sin(f2);\n res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);\n }\n df = f2 - f1;\n var c1 = math.cos(f1),\n s1 = math.sin(f1),\n c2 = math.cos(f2),\n s2 = math.sin(f2),\n t = math.tan(df / 4),\n hx = 4 / 3 * rx * t,\n hy = 4 / 3 * ry * t,\n m1 = [x1, y1],\n m2 = [x1 + hx * s1, y1 - hy * c1],\n m3 = [x2 + hx * s2, y2 - hy * c2],\n m4 = [x2, y2];\n m2[0] = 2 * m1[0] - m2[0];\n m2[1] = 2 * m1[1] - m2[1];\n if (recursive) {\n return [m2, m3, m4][concat](res);\n } else {\n res = [m2, m3, m4][concat](res).join()[split](\",\");\n var newres = [];\n for (var i = 0, ii = res.length; i < ii; i++) {\n newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;\n }\n return newres;\n }\n },\n findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n var t1 = 1 - t;\n return {\n x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,\n y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y\n };\n },\n curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),\n b = 2 * (c1x - p1x) - 2 * (c2x - c1x),\n c = p1x - c1x,\n t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,\n t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,\n y = [p1y, p2y],\n x = [p1x, p2x],\n dot;\n abs(t1) > \"1e12\" && (t1 = .5);\n abs(t2) > \"1e12\" && (t2 = .5);\n if (t1 > 0 && t1 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n x.push(dot.x);\n y.push(dot.y);\n }\n if (t2 > 0 && t2 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n x.push(dot.x);\n y.push(dot.y);\n }\n a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);\n b = 2 * (c1y - p1y) - 2 * (c2y - c1y);\n c = p1y - c1y;\n t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;\n t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;\n abs(t1) > \"1e12\" && (t1 = .5);\n abs(t2) > \"1e12\" && (t2 = .5);\n if (t1 > 0 && t1 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n x.push(dot.x);\n y.push(dot.y);\n }\n if (t2 > 0 && t2 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n x.push(dot.x);\n y.push(dot.y);\n }\n return {\n min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},\n max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}\n };\n }),\n path2curve = R._path2curve = cacher(function (path, path2) {\n var pth = !path2 && paths(path);\n if (!path2 && pth.curve) {\n return pathClone(pth.curve);\n }\n var p = pathToAbsolute(path),\n p2 = path2 && pathToAbsolute(path2),\n attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n processPath = function (path, d, pcom) {\n var nx, ny, tq = {T:1, Q:1};\n if (!path) {\n return [\"C\", d.x, d.y, d.x, d.y, d.x, d.y];\n }\n !(path[0] in tq) && (d.qx = d.qy = null);\n switch (path[0]) {\n case \"M\":\n d.X = path[1];\n d.Y = path[2];\n break;\n case \"A\":\n path = [\"C\"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));\n break;\n case \"S\":\n if (pcom == \"C\" || pcom == \"S\") { // In \"S\" case we have to take into account, if the previous command is C/S.\n nx = d.x * 2 - d.bx; // And reflect the previous\n ny = d.y * 2 - d.by; // command's control point relative to the current point.\n }\n else { // or some else or nothing\n nx = d.x;\n ny = d.y;\n }\n path = [\"C\", nx, ny][concat](path.slice(1));\n break;\n case \"T\":\n if (pcom == \"Q\" || pcom == \"T\") { // In \"T\" case we have to take into account, if the previous command is Q/T.\n d.qx = d.x * 2 - d.qx; // And make a reflection similar\n d.qy = d.y * 2 - d.qy; // to case \"S\".\n }\n else { // or something else or nothing\n d.qx = d.x;\n d.qy = d.y;\n }\n path = [\"C\"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));\n break;\n case \"Q\":\n d.qx = path[1];\n d.qy = path[2];\n path = [\"C\"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));\n break;\n case \"L\":\n path = [\"C\"][concat](l2c(d.x, d.y, path[1], path[2]));\n break;\n case \"H\":\n path = [\"C\"][concat](l2c(d.x, d.y, path[1], d.y));\n break;\n case \"V\":\n path = [\"C\"][concat](l2c(d.x, d.y, d.x, path[1]));\n break;\n case \"Z\":\n path = [\"C\"][concat](l2c(d.x, d.y, d.X, d.Y));\n break;\n }\n return path;\n },\n fixArc = function (pp, i) {\n if (pp[i].length > 7) {\n pp[i].shift();\n var pi = pp[i];\n while (pi.length) {\n pcoms1[i]=\"A\"; // if created multiple C:s, their original seg is saved\n p2 && (pcoms2[i]=\"A\"); // the same as above\n pp.splice(i++, 0, [\"C\"][concat](pi.splice(0, 6)));\n }\n pp.splice(i, 1);\n ii = mmax(p.length, p2 && p2.length || 0);\n }\n },\n fixM = function (path1, path2, a1, a2, i) {\n if (path1 && path2 && path1[i][0] == \"M\" && path2[i][0] != \"M\") {\n path2.splice(i, 0, [\"M\", a2.x, a2.y]);\n a1.bx = 0;\n a1.by = 0;\n a1.x = path1[i][1];\n a1.y = path1[i][2];\n ii = mmax(p.length, p2 && p2.length || 0);\n }\n },\n pcoms1 = [], // path commands of original path p\n pcoms2 = [], // path commands of original path p2\n pfirst = \"\", // temporary holder for original path command\n pcom = \"\"; // holder for previous path command of original path\n for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {\n p[i] && (pfirst = p[i][0]); // save current path command\n\n if (pfirst != \"C\") // C is not saved yet, because it may be result of conversion\n {\n pcoms1[i] = pfirst; // Save current path command\n i && ( pcom = pcoms1[i-1]); // Get previous path command pcom\n }\n p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath\n\n if (pcoms1[i] != \"A\" && pfirst == \"C\") pcoms1[i] = \"C\"; // A is the only command\n // which may produce multiple C:s\n // so we have to make sure that C is also C in original path\n\n fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1\n\n if (p2) { // the same procedures is done to p2\n p2[i] && (pfirst = p2[i][0]);\n if (pfirst != \"C\")\n {\n pcoms2[i] = pfirst;\n i && (pcom = pcoms2[i-1]);\n }\n p2[i] = processPath(p2[i], attrs2, pcom);\n\n if (pcoms2[i]!=\"A\" && pfirst==\"C\") pcoms2[i]=\"C\";\n\n fixArc(p2, i);\n }\n fixM(p, p2, attrs, attrs2, i);\n fixM(p2, p, attrs2, attrs, i);\n var seg = p[i],\n seg2 = p2 && p2[i],\n seglen = seg.length,\n seg2len = p2 && seg2.length;\n attrs.x = seg[seglen - 2];\n attrs.y = seg[seglen - 1];\n attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;\n attrs.by = toFloat(seg[seglen - 3]) || attrs.y;\n attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);\n attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);\n attrs2.x = p2 && seg2[seg2len - 2];\n attrs2.y = p2 && seg2[seg2len - 1];\n }\n if (!p2) {\n pth.curve = pathClone(p);\n }\n return p2 ? [p, p2] : p;\n }, null, pathClone),\n parseDots = R._parseDots = cacher(function (gradient) {\n var dots = [];\n for (var i = 0, ii = gradient.length; i < ii; i++) {\n var dot = {},\n par = gradient[i].match(/^([^:]*):?([\\d\\.]*)/);\n dot.color = R.getRGB(par[1]);\n if (dot.color.error) {\n return null;\n }\n dot.opacity = dot.color.opacity;\n dot.color = dot.color.hex;\n par[2] && (dot.offset = par[2] + \"%\");\n dots.push(dot);\n }\n for (i = 1, ii = dots.length - 1; i < ii; i++) {\n if (!dots[i].offset) {\n var start = toFloat(dots[i - 1].offset || 0),\n end = 0;\n for (var j = i + 1; j < ii; j++) {\n if (dots[j].offset) {\n end = dots[j].offset;\n break;\n }\n }\n if (!end) {\n end = 100;\n j = ii;\n }\n end = toFloat(end);\n var d = (end - start) / (j - i + 1);\n for (; i < j; i++) {\n start += d;\n dots[i].offset = start + \"%\";\n }\n }\n }\n return dots;\n }),\n tear = R._tear = function (el, paper) {\n el == paper.top && (paper.top = el.prev);\n el == paper.bottom && (paper.bottom = el.next);\n el.next && (el.next.prev = el.prev);\n el.prev && (el.prev.next = el.next);\n },\n tofront = R._tofront = function (el, paper) {\n if (paper.top === el) {\n return;\n }\n tear(el, paper);\n el.next = null;\n el.prev = paper.top;\n paper.top.next = el;\n paper.top = el;\n },\n toback = R._toback = function (el, paper) {\n if (paper.bottom === el) {\n return;\n }\n tear(el, paper);\n el.next = paper.bottom;\n el.prev = null;\n paper.bottom.prev = el;\n paper.bottom = el;\n },\n insertafter = R._insertafter = function (el, el2, paper) {\n tear(el, paper);\n el2 == paper.top && (paper.top = el);\n el2.next && (el2.next.prev = el);\n el.next = el2.next;\n el.prev = el2;\n el2.next = el;\n },\n insertbefore = R._insertbefore = function (el, el2, paper) {\n tear(el, paper);\n el2 == paper.bottom && (paper.bottom = el);\n el2.prev && (el2.prev.next = el);\n el.prev = el2.prev;\n el2.prev = el;\n el.next = el2;\n },\n /*\\\n * Raphael.toMatrix\n [ method ]\n **\n * Utility method\n **\n * Returns matrix of transformations applied to a given path\n > Parameters\n - path (string) path string\n - transform (string|array) transformation string\n = (object) @Matrix\n \\*/\n toMatrix = R.toMatrix = function (path, transform) {\n var bb = pathDimensions(path),\n el = {\n _: {\n transform: E\n },\n getBBox: function () {\n return bb;\n }\n };\n extractTransform(el, transform);\n return el.matrix;\n },\n /*\\\n * Raphael.transformPath\n [ method ]\n **\n * Utility method\n **\n * Returns path transformed by a given transformation\n > Parameters\n - path (string) path string\n - transform (string|array) transformation string\n = (string) path\n \\*/\n transformPath = R.transformPath = function (path, transform) {\n return mapPath(path, toMatrix(path, transform));\n },\n extractTransform = R._extractTransform = function (el, tstr) {\n if (tstr == null) {\n return el._.transform;\n }\n tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, el._.transform || E);\n var tdata = R.parseTransformString(tstr),\n deg = 0,\n dx = 0,\n dy = 0,\n sx = 1,\n sy = 1,\n _ = el._,\n m = new Matrix;\n _.transform = tdata || [];\n if (tdata) {\n for (var i = 0, ii = tdata.length; i < ii; i++) {\n var t = tdata[i],\n tlen = t.length,\n command = Str(t[0]).toLowerCase(),\n absolute = t[0] != command,\n inver = absolute ? m.invert() : 0,\n x1,\n y1,\n x2,\n y2,\n bb;\n if (command == \"t\" && tlen == 3) {\n if (absolute) {\n x1 = inver.x(0, 0);\n y1 = inver.y(0, 0);\n x2 = inver.x(t[1], t[2]);\n y2 = inver.y(t[1], t[2]);\n m.translate(x2 - x1, y2 - y1);\n } else {\n m.translate(t[1], t[2]);\n }\n } else if (command == \"r\") {\n if (tlen == 2) {\n bb = bb || el.getBBox(1);\n m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n deg += t[1];\n } else if (tlen == 4) {\n if (absolute) {\n x2 = inver.x(t[2], t[3]);\n y2 = inver.y(t[2], t[3]);\n m.rotate(t[1], x2, y2);\n } else {\n m.rotate(t[1], t[2], t[3]);\n }\n deg += t[1];\n }\n } else if (command == \"s\") {\n if (tlen == 2 || tlen == 3) {\n bb = bb || el.getBBox(1);\n m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n sx *= t[1];\n sy *= t[tlen - 1];\n } else if (tlen == 5) {\n if (absolute) {\n x2 = inver.x(t[3], t[4]);\n y2 = inver.y(t[3], t[4]);\n m.scale(t[1], t[2], x2, y2);\n } else {\n m.scale(t[1], t[2], t[3], t[4]);\n }\n sx *= t[1];\n sy *= t[2];\n }\n } else if (command == \"m\" && tlen == 7) {\n m.add(t[1], t[2], t[3], t[4], t[5], t[6]);\n }\n _.dirtyT = 1;\n el.matrix = m;\n }\n }\n\n /*\\\n * Element.matrix\n [ property (object) ]\n **\n * Keeps @Matrix object, which represents element transformation\n \\*/\n el.matrix = m;\n\n _.sx = sx;\n _.sy = sy;\n _.deg = deg;\n _.dx = dx = m.e;\n _.dy = dy = m.f;\n\n if (sx == 1 && sy == 1 && !deg && _.bbox) {\n _.bbox.x += +dx;\n _.bbox.y += +dy;\n } else {\n _.dirtyT = 1;\n }\n },\n getEmpty = function (item) {\n var l = item[0];\n switch (l.toLowerCase()) {\n case \"t\": return [l, 0, 0];\n case \"m\": return [l, 1, 0, 0, 1, 0, 0];\n case \"r\": if (item.length == 4) {\n return [l, 0, item[2], item[3]];\n } else {\n return [l, 0];\n }\n case \"s\": if (item.length == 5) {\n return [l, 1, 1, item[3], item[4]];\n } else if (item.length == 3) {\n return [l, 1, 1];\n } else {\n return [l, 1];\n }\n }\n },\n equaliseTransform = R._equaliseTransform = function (t1, t2) {\n t2 = Str(t2).replace(/\\.{3}|\\u2026/g, t1);\n t1 = R.parseTransformString(t1) || [];\n t2 = R.parseTransformString(t2) || [];\n var maxlength = mmax(t1.length, t2.length),\n from = [],\n to = [],\n i = 0, j, jj,\n tt1, tt2;\n for (; i < maxlength; i++) {\n tt1 = t1[i] || getEmpty(t2[i]);\n tt2 = t2[i] || getEmpty(tt1);\n if ((tt1[0] != tt2[0]) ||\n (tt1[0].toLowerCase() == \"r\" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||\n (tt1[0].toLowerCase() == \"s\" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))\n ) {\n return;\n }\n from[i] = [];\n to[i] = [];\n for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {\n j in tt1 && (from[i][j] = tt1[j]);\n j in tt2 && (to[i][j] = tt2[j]);\n }\n }\n return {\n from: from,\n to: to\n };\n };\n R._getContainer = function (x, y, w, h) {\n var container;\n container = h == null && !R.is(x, \"object\") ? g.doc.getElementById(x) : x;\n if (container == null) {\n return;\n }\n if (container.tagName) {\n if (y == null) {\n return {\n container: container,\n width: container.style.pixelWidth || container.offsetWidth,\n height: container.style.pixelHeight || container.offsetHeight\n };\n } else {\n return {\n container: container,\n width: y,\n height: w\n };\n }\n }\n return {\n container: 1,\n x: x,\n y: y,\n width: w,\n height: h\n };\n };\n /*\\\n * Raphael.pathToRelative\n [ method ]\n **\n * Utility method\n **\n * Converts path to relative form\n > Parameters\n - pathString (string|array) path string or array of segments\n = (array) array of segments.\n \\*/\n R.pathToRelative = pathToRelative;\n R._engine = {};\n /*\\\n * Raphael.path2curve\n [ method ]\n **\n * Utility method\n **\n * Converts path to a new path where all segments are cubic bezier curves.\n > Parameters\n - pathString (string|array) path string or array of segments\n = (array) array of segments.\n \\*/\n R.path2curve = path2curve;\n /*\\\n * Raphael.matrix\n [ method ]\n **\n * Utility method\n **\n * Returns matrix based on given parameters.\n > Parameters\n - a (number)\n - b (number)\n - c (number)\n - d (number)\n - e (number)\n - f (number)\n = (object) @Matrix\n \\*/\n R.matrix = function (a, b, c, d, e, f) {\n return new Matrix(a, b, c, d, e, f);\n };\n function Matrix(a, b, c, d, e, f) {\n if (a != null) {\n this.a = +a;\n this.b = +b;\n this.c = +c;\n this.d = +d;\n this.e = +e;\n this.f = +f;\n } else {\n this.a = 1;\n this.b = 0;\n this.c = 0;\n this.d = 1;\n this.e = 0;\n this.f = 0;\n }\n }\n (function (matrixproto) {\n /*\\\n * Matrix.add\n [ method ]\n **\n * Adds given matrix to existing one.\n > Parameters\n - a (number)\n - b (number)\n - c (number)\n - d (number)\n - e (number)\n - f (number)\n or\n - matrix (object) @Matrix\n \\*/\n matrixproto.add = function (a, b, c, d, e, f) {\n var out = [[], [], []],\n m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],\n matrix = [[a, c, e], [b, d, f], [0, 0, 1]],\n x, y, z, res;\n\n if (a && a instanceof Matrix) {\n matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];\n }\n\n for (x = 0; x < 3; x++) {\n for (y = 0; y < 3; y++) {\n res = 0;\n for (z = 0; z < 3; z++) {\n res += m[x][z] * matrix[z][y];\n }\n out[x][y] = res;\n }\n }\n this.a = out[0][0];\n this.b = out[1][0];\n this.c = out[0][1];\n this.d = out[1][1];\n this.e = out[0][2];\n this.f = out[1][2];\n };\n /*\\\n * Matrix.invert\n [ method ]\n **\n * Returns inverted version of the matrix\n = (object) @Matrix\n \\*/\n matrixproto.invert = function () {\n var me = this,\n x = me.a * me.d - me.b * me.c;\n return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);\n };\n /*\\\n * Matrix.clone\n [ method ]\n **\n * Returns copy of the matrix\n = (object) @Matrix\n \\*/\n matrixproto.clone = function () {\n return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);\n };\n /*\\\n * Matrix.translate\n [ method ]\n **\n * Translate the matrix\n > Parameters\n - x (number)\n - y (number)\n \\*/\n matrixproto.translate = function (x, y) {\n this.add(1, 0, 0, 1, x, y);\n };\n /*\\\n * Matrix.scale\n [ method ]\n **\n * Scales the matrix\n > Parameters\n - x (number)\n - y (number) #optional\n - cx (number) #optional\n - cy (number) #optional\n \\*/\n matrixproto.scale = function (x, y, cx, cy) {\n y == null && (y = x);\n (cx || cy) && this.add(1, 0, 0, 1, cx, cy);\n this.add(x, 0, 0, y, 0, 0);\n (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);\n };\n /*\\\n * Matrix.rotate\n [ method ]\n **\n * Rotates the matrix\n > Parameters\n - a (number)\n - x (number)\n - y (number)\n \\*/\n matrixproto.rotate = function (a, x, y) {\n a = R.rad(a);\n x = x || 0;\n y = y || 0;\n var cos = +math.cos(a).toFixed(9),\n sin = +math.sin(a).toFixed(9);\n this.add(cos, sin, -sin, cos, x, y);\n this.add(1, 0, 0, 1, -x, -y);\n };\n /*\\\n * Matrix.x\n [ method ]\n **\n * Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y\n > Parameters\n - x (number)\n - y (number)\n = (number) x\n \\*/\n matrixproto.x = function (x, y) {\n return x * this.a + y * this.c + this.e;\n };\n /*\\\n * Matrix.y\n [ method ]\n **\n * Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x\n > Parameters\n - x (number)\n - y (number)\n = (number) y\n \\*/\n matrixproto.y = function (x, y) {\n return x * this.b + y * this.d + this.f;\n };\n matrixproto.get = function (i) {\n return +this[Str.fromCharCode(97 + i)].toFixed(4);\n };\n matrixproto.toString = function () {\n return R.svg ?\n \"matrix(\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + \")\" :\n [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();\n };\n matrixproto.toFilter = function () {\n return \"progid:DXImageTransform.Microsoft.Matrix(M11=\" + this.get(0) +\n \", M12=\" + this.get(2) + \", M21=\" + this.get(1) + \", M22=\" + this.get(3) +\n \", Dx=\" + this.get(4) + \", Dy=\" + this.get(5) + \", sizingmethod='auto expand')\";\n };\n matrixproto.offset = function () {\n return [this.e.toFixed(4), this.f.toFixed(4)];\n };\n function norm(a) {\n return a[0] * a[0] + a[1] * a[1];\n }\n function normalize(a) {\n var mag = math.sqrt(norm(a));\n a[0] && (a[0] /= mag);\n a[1] && (a[1] /= mag);\n }\n /*\\\n * Matrix.split\n [ method ]\n **\n * Splits matrix into primitive transformations\n = (object) in format:\n o dx (number) translation by x\n o dy (number) translation by y\n o scalex (number) scale by x\n o scaley (number) scale by y\n o shear (number) shear\n o rotate (number) rotation in deg\n o isSimple (boolean) could it be represented via simple transformations\n \\*/\n matrixproto.split = function () {\n var out = {};\n // translation\n out.dx = this.e;\n out.dy = this.f;\n\n // scale and shear\n var row = [[this.a, this.c], [this.b, this.d]];\n out.scalex = math.sqrt(norm(row[0]));\n normalize(row[0]);\n\n out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];\n row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];\n\n out.scaley = math.sqrt(norm(row[1]));\n normalize(row[1]);\n out.shear /= out.scaley;\n\n // rotation\n var sin = -row[0][1],\n cos = row[1][1];\n if (cos < 0) {\n out.rotate = R.deg(math.acos(cos));\n if (sin < 0) {\n out.rotate = 360 - out.rotate;\n }\n } else {\n out.rotate = R.deg(math.asin(sin));\n }\n\n out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);\n out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;\n out.noRotation = !+out.shear.toFixed(9) && !out.rotate;\n return out;\n };\n /*\\\n * Matrix.toTransformString\n [ method ]\n **\n * Return transform string that represents given matrix\n = (string) transform string\n \\*/\n matrixproto.toTransformString = function (shorter) {\n var s = shorter || this[split]();\n if (s.isSimple) {\n s.scalex = +s.scalex.toFixed(4);\n s.scaley = +s.scaley.toFixed(4);\n s.rotate = +s.rotate.toFixed(4);\n return (s.dx || s.dy ? \"t\" + [s.dx, s.dy] : E) +\n (s.scalex != 1 || s.scaley != 1 ? \"s\" + [s.scalex, s.scaley, 0, 0] : E) +\n (s.rotate ? \"r\" + [s.rotate, 0, 0] : E);\n } else {\n return \"m\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];\n }\n };\n })(Matrix.prototype);\n\n var preventDefault = function () {\n this.returnValue = false;\n },\n preventTouch = function () {\n return this.originalEvent.preventDefault();\n },\n stopPropagation = function () {\n this.cancelBubble = true;\n },\n stopTouch = function () {\n return this.originalEvent.stopPropagation();\n },\n getEventPosition = function (e) {\n var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;\n\n return {\n x: e.clientX + scrollX,\n y: e.clientY + scrollY\n };\n },\n addEvent = (function () {\n if (g.doc.addEventListener) {\n return function (obj, type, fn, element) {\n var f = function (e) {\n var pos = getEventPosition(e);\n return fn.call(element, e, pos.x, pos.y);\n };\n obj.addEventListener(type, f, false);\n\n if (supportsTouch && touchMap[type]) {\n var _f = function (e) {\n var pos = getEventPosition(e),\n olde = e;\n\n for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {\n if (e.targetTouches[i].target == obj) {\n e = e.targetTouches[i];\n e.originalEvent = olde;\n e.preventDefault = preventTouch;\n e.stopPropagation = stopTouch;\n break;\n }\n }\n\n return fn.call(element, e, pos.x, pos.y);\n };\n obj.addEventListener(touchMap[type], _f, false);\n }\n\n return function () {\n obj.removeEventListener(type, f, false);\n\n if (supportsTouch && touchMap[type])\n obj.removeEventListener(touchMap[type], _f, false);\n\n return true;\n };\n };\n } else if (g.doc.attachEvent) {\n return function (obj, type, fn, element) {\n var f = function (e) {\n e = e || g.win.event;\n var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n x = e.clientX + scrollX,\n y = e.clientY + scrollY;\n e.preventDefault = e.preventDefault || preventDefault;\n e.stopPropagation = e.stopPropagation || stopPropagation;\n return fn.call(element, e, x, y);\n };\n obj.attachEvent(\"on\" + type, f);\n var detacher = function () {\n obj.detachEvent(\"on\" + type, f);\n return true;\n };\n return detacher;\n };\n }\n })(),\n drag = [],\n dragMove = function (e) {\n var x = e.clientX,\n y = e.clientY,\n scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n dragi,\n j = drag.length;\n while (j--) {\n dragi = drag[j];\n if (supportsTouch && e.touches) {\n var i = e.touches.length,\n touch;\n while (i--) {\n touch = e.touches[i];\n if (touch.identifier == dragi.el._drag.id) {\n x = touch.clientX;\n y = touch.clientY;\n (e.originalEvent ? e.originalEvent : e).preventDefault();\n break;\n }\n }\n } else {\n e.preventDefault();\n }\n var node = dragi.el.node,\n o,\n next = node.nextSibling,\n parent = node.parentNode,\n display = node.style.display;\n g.win.opera && parent.removeChild(node);\n node.style.display = \"none\";\n o = dragi.el.paper.getElementByPoint(x, y);\n node.style.display = display;\n g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));\n o && eve(\"raphael.drag.over.\" + dragi.el.id, dragi.el, o);\n x += scrollX;\n y += scrollY;\n eve(\"raphael.drag.move.\" + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);\n }\n },\n dragUp = function (e) {\n R.unmousemove(dragMove).unmouseup(dragUp);\n var i = drag.length,\n dragi;\n while (i--) {\n dragi = drag[i];\n dragi.el._drag = {};\n eve(\"raphael.drag.end.\" + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);\n }\n drag = [];\n },\n /*\\\n * Raphael.el\n [ property (object) ]\n **\n * You can add your own method to elements. This is usefull when you want to hack default functionality or\n * want to wrap some common transformation or attributes in one method. In difference to canvas methods,\n * you can redefine element method at any time. Expending element methods wouldn’t affect set.\n > Usage\n | Raphael.el.red = function () {\n | this.attr({fill: \"#f00\"});\n | };\n | // then use it\n | paper.circle(100, 100, 20).red();\n \\*/\n elproto = R.el = {};\n /*\\\n * Element.click\n [ method ]\n **\n * Adds event handler for click for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unclick\n [ method ]\n **\n * Removes event handler for click for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.dblclick\n [ method ]\n **\n * Adds event handler for double click for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.undblclick\n [ method ]\n **\n * Removes event handler for double click for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mousedown\n [ method ]\n **\n * Adds event handler for mousedown for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmousedown\n [ method ]\n **\n * Removes event handler for mousedown for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mousemove\n [ method ]\n **\n * Adds event handler for mousemove for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmousemove\n [ method ]\n **\n * Removes event handler for mousemove for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mouseout\n [ method ]\n **\n * Adds event handler for mouseout for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmouseout\n [ method ]\n **\n * Removes event handler for mouseout for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mouseover\n [ method ]\n **\n * Adds event handler for mouseover for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmouseover\n [ method ]\n **\n * Removes event handler for mouseover for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mouseup\n [ method ]\n **\n * Adds event handler for mouseup for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmouseup\n [ method ]\n **\n * Removes event handler for mouseup for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchstart\n [ method ]\n **\n * Adds event handler for touchstart for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchstart\n [ method ]\n **\n * Removes event handler for touchstart for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchmove\n [ method ]\n **\n * Adds event handler for touchmove for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchmove\n [ method ]\n **\n * Removes event handler for touchmove for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchend\n [ method ]\n **\n * Adds event handler for touchend for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchend\n [ method ]\n **\n * Removes event handler for touchend for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchcancel\n [ method ]\n **\n * Adds event handler for touchcancel for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchcancel\n [ method ]\n **\n * Removes event handler for touchcancel for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n for (var i = events.length; i--;) {\n (function (eventName) {\n R[eventName] = elproto[eventName] = function (fn, scope) {\n if (R.is(fn, \"function\")) {\n this.events = this.events || [];\n this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});\n }\n return this;\n };\n R[\"un\" + eventName] = elproto[\"un\" + eventName] = function (fn) {\n var events = this.events || [],\n l = events.length;\n while (l--){\n if (events[l].name == eventName && (R.is(fn, \"undefined\") || events[l].f == fn)) {\n events[l].unbind();\n events.splice(l, 1);\n !events.length && delete this.events;\n }\n }\n return this;\n };\n })(events[i]);\n }\n\n /*\\\n * Element.data\n [ method ]\n **\n * Adds or retrieves given value asociated with given key.\n **\n * See also @Element.removeData\n > Parameters\n - key (string) key to store data\n - value (any) #optional value to store\n = (object) @Element\n * or, if value is not specified:\n = (any) value\n * or, if key and value are not specified:\n = (object) Key/value pairs for all the data associated with the element.\n > Usage\n | for (var i = 0, i < 5, i++) {\n | paper.circle(10 + 15 * i, 10, 10)\n | .attr({fill: \"#000\"})\n | .data(\"i\", i)\n | .click(function () {\n | alert(this.data(\"i\"));\n | });\n | }\n \\*/\n elproto.data = function (key, value) {\n var data = eldata[this.id] = eldata[this.id] || {};\n if (arguments.length == 0) {\n return data;\n }\n if (arguments.length == 1) {\n if (R.is(key, \"object\")) {\n for (var i in key) if (key[has](i)) {\n this.data(i, key[i]);\n }\n return this;\n }\n eve(\"raphael.data.get.\" + this.id, this, data[key], key);\n return data[key];\n }\n data[key] = value;\n eve(\"raphael.data.set.\" + this.id, this, value, key);\n return this;\n };\n /*\\\n * Element.removeData\n [ method ]\n **\n * Removes value associated with an element by given key.\n * If key is not provided, removes all the data of the element.\n > Parameters\n - key (string) #optional key\n = (object) @Element\n \\*/\n elproto.removeData = function (key) {\n if (key == null) {\n eldata[this.id] = {};\n } else {\n eldata[this.id] && delete eldata[this.id][key];\n }\n return this;\n };\n /*\\\n * Element.getData\n [ method ]\n **\n * Retrieves the element data\n = (object) data\n \\*/\n elproto.getData = function () {\n return clone(eldata[this.id] || {});\n };\n /*\\\n * Element.hover\n [ method ]\n **\n * Adds event handlers for hover for the element.\n > Parameters\n - f_in (function) handler for hover in\n - f_out (function) handler for hover out\n - icontext (object) #optional context for hover in handler\n - ocontext (object) #optional context for hover out handler\n = (object) @Element\n \\*/\n elproto.hover = function (f_in, f_out, scope_in, scope_out) {\n return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);\n };\n /*\\\n * Element.unhover\n [ method ]\n **\n * Removes event handlers for hover for the element.\n > Parameters\n - f_in (function) handler for hover in\n - f_out (function) handler for hover out\n = (object) @Element\n \\*/\n elproto.unhover = function (f_in, f_out) {\n return this.unmouseover(f_in).unmouseout(f_out);\n };\n var draggable = [];\n /*\\\n * Element.drag\n [ method ]\n **\n * Adds event handlers for drag of the element.\n > Parameters\n - onmove (function) handler for moving\n - onstart (function) handler for drag start\n - onend (function) handler for drag end\n - mcontext (object) #optional context for moving handler\n - scontext (object) #optional context for drag start handler\n - econtext (object) #optional context for drag end handler\n * Additionaly following `drag` events will be triggered: `drag.start.` on start,\n * `drag.end.` on end and `drag.move.` on every move. When element will be dragged over another element\n * `drag.over.` will be fired as well.\n *\n * Start event and start handler will be called in specified context or in context of the element with following parameters:\n o x (number) x position of the mouse\n o y (number) y position of the mouse\n o event (object) DOM event object\n * Move event and move handler will be called in specified context or in context of the element with following parameters:\n o dx (number) shift by x from the start point\n o dy (number) shift by y from the start point\n o x (number) x position of the mouse\n o y (number) y position of the mouse\n o event (object) DOM event object\n * End event and end handler will be called in specified context or in context of the element with following parameters:\n o event (object) DOM event object\n = (object) @Element\n \\*/\n elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {\n function start(e) {\n (e.originalEvent || e).preventDefault();\n var x = e.clientX,\n y = e.clientY,\n scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;\n this._drag.id = e.identifier;\n if (supportsTouch && e.touches) {\n var i = e.touches.length, touch;\n while (i--) {\n touch = e.touches[i];\n this._drag.id = touch.identifier;\n if (touch.identifier == this._drag.id) {\n x = touch.clientX;\n y = touch.clientY;\n break;\n }\n }\n }\n this._drag.x = x + scrollX;\n this._drag.y = y + scrollY;\n !drag.length && R.mousemove(dragMove).mouseup(dragUp);\n drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});\n onstart && eve.on(\"raphael.drag.start.\" + this.id, onstart);\n onmove && eve.on(\"raphael.drag.move.\" + this.id, onmove);\n onend && eve.on(\"raphael.drag.end.\" + this.id, onend);\n eve(\"raphael.drag.start.\" + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);\n }\n this._drag = {};\n draggable.push({el: this, start: start});\n this.mousedown(start);\n return this;\n };\n /*\\\n * Element.onDragOver\n [ method ]\n **\n * Shortcut for assigning event handler for `drag.over.` event, where id is id of the element (see @Element.id).\n > Parameters\n - f (function) handler for event, first argument would be the element you are dragging over\n \\*/\n elproto.onDragOver = function (f) {\n f ? eve.on(\"raphael.drag.over.\" + this.id, f) : eve.unbind(\"raphael.drag.over.\" + this.id);\n };\n /*\\\n * Element.undrag\n [ method ]\n **\n * Removes all drag event handlers from given element.\n \\*/\n elproto.undrag = function () {\n var i = draggable.length;\n while (i--) if (draggable[i].el == this) {\n this.unmousedown(draggable[i].start);\n draggable.splice(i, 1);\n eve.unbind(\"raphael.drag.*.\" + this.id);\n }\n !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);\n drag = [];\n };\n /*\\\n * Paper.circle\n [ method ]\n **\n * Draws a circle.\n **\n > Parameters\n **\n - x (number) x coordinate of the centre\n - y (number) y coordinate of the centre\n - r (number) radius\n = (object) Raphaël element object with type “circleâ€\n **\n > Usage\n | var c = paper.circle(50, 50, 40);\n \\*/\n paperproto.circle = function (x, y, r) {\n var out = R._engine.circle(this, x || 0, y || 0, r || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.rect\n [ method ]\n *\n * Draws a rectangle.\n **\n > Parameters\n **\n - x (number) x coordinate of the top left corner\n - y (number) y coordinate of the top left corner\n - width (number) width\n - height (number) height\n - r (number) #optional radius for rounded corners, default is 0\n = (object) Raphaël element object with type “rectâ€\n **\n > Usage\n | // regular rectangle\n | var c = paper.rect(10, 10, 50, 50);\n | // rectangle with rounded corners\n | var c = paper.rect(40, 40, 50, 50, 10);\n \\*/\n paperproto.rect = function (x, y, w, h, r) {\n var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.ellipse\n [ method ]\n **\n * Draws an ellipse.\n **\n > Parameters\n **\n - x (number) x coordinate of the centre\n - y (number) y coordinate of the centre\n - rx (number) horizontal radius\n - ry (number) vertical radius\n = (object) Raphaël element object with type “ellipseâ€\n **\n > Usage\n | var c = paper.ellipse(50, 50, 40, 20);\n \\*/\n paperproto.ellipse = function (x, y, rx, ry) {\n var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.path\n [ method ]\n **\n * Creates a path element by given path data string.\n > Parameters\n - pathString (string) #optional path string in SVG format.\n * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example:\n | \"M10,20L30,40\"\n * Here we can see two commands: “Mâ€, with arguments `(10, 20)` and “L†with arguments `(30, 40)`. Upper case letter mean command is absolute, lower case—relative.\n *\n # Here is short list of commands available, for more details see SVG path string format .
\n # Command Name Parameters \n # M moveto (x y)+ \n # Z closepath (none) \n # L lineto (x y)+ \n # H horizontal lineto x+ \n # V vertical lineto y+ \n # C curveto (x1 y1 x2 y2 x y)+ \n # S smooth curveto (x2 y2 x y)+ \n # Q quadratic Bézier curveto (x1 y1 x y)+ \n # T smooth quadratic Bézier curveto (x y)+ \n # A elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ \n # R Catmull-Rom curveto *x1 y1 (x y)+
\n * * “Catmull-Rom curveto†is a not standard SVG command and added in 2.0 to make life easier.\n * Note: there is a special case when path consist of just three commands: “M10,10R…zâ€. In this case path will smoothly connects to its beginning.\n > Usage\n | var c = paper.path(\"M10 10L90 90\");\n | // draw a diagonal line:\n | // move to 10,10, line to 90,90\n * For example of path strings, check out these icons: http://raphaeljs.com/icons/\n \\*/\n paperproto.path = function (pathString) {\n pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);\n var out = R._engine.path(R.format[apply](R, arguments), this);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.image\n [ method ]\n **\n * Embeds an image into the surface.\n **\n > Parameters\n **\n - src (string) URI of the source image\n - x (number) x coordinate position\n - y (number) y coordinate position\n - width (number) width of the image\n - height (number) height of the image\n = (object) Raphaël element object with type “imageâ€\n **\n > Usage\n | var c = paper.image(\"apple.png\", 10, 10, 80, 80);\n \\*/\n paperproto.image = function (src, x, y, w, h) {\n var out = R._engine.image(this, src || \"about:blank\", x || 0, y || 0, w || 0, h || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.text\n [ method ]\n **\n * Draws a text string. If you need line breaks, put “\\n†in the string.\n **\n > Parameters\n **\n - x (number) x coordinate position\n - y (number) y coordinate position\n - text (string) The text string to draw\n = (object) Raphaël element object with type “textâ€\n **\n > Usage\n | var t = paper.text(50, 50, \"Raphaël\\nkicks\\nbutt!\");\n \\*/\n paperproto.text = function (x, y, text) {\n var out = R._engine.text(this, x || 0, y || 0, Str(text));\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.set\n [ method ]\n **\n * Creates array-like object to keep and operate several elements at once.\n * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements.\n * Sets act as pseudo elements — all methods available to an element can be used on a set.\n = (object) array-like object that represents set of elements\n **\n > Usage\n | var st = paper.set();\n | st.push(\n | paper.circle(10, 10, 5),\n | paper.circle(30, 10, 5)\n | );\n | st.attr({fill: \"red\"}); // changes the fill of both circles\n \\*/\n paperproto.set = function (itemsArray) {\n !R.is(itemsArray, \"array\") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));\n var out = new Set(itemsArray);\n this.__set__ && this.__set__.push(out);\n out[\"paper\"] = this;\n out[\"type\"] = \"set\";\n return out;\n };\n /*\\\n * Paper.setStart\n [ method ]\n **\n * Creates @Paper.set. All elements that will be created after calling this method and before calling\n * @Paper.setFinish will be added to the set.\n **\n > Usage\n | paper.setStart();\n | paper.circle(10, 10, 5),\n | paper.circle(30, 10, 5)\n | var st = paper.setFinish();\n | st.attr({fill: \"red\"}); // changes the fill of both circles\n \\*/\n paperproto.setStart = function (set) {\n this.__set__ = set || this.set();\n };\n /*\\\n * Paper.setFinish\n [ method ]\n **\n * See @Paper.setStart. This method finishes catching and returns resulting set.\n **\n = (object) set\n \\*/\n paperproto.setFinish = function (set) {\n var out = this.__set__;\n delete this.__set__;\n return out;\n };\n /*\\\n * Paper.getSize\n [ method ]\n **\n * Obtains current paper actual size.\n **\n = (object)\n \\*/\n paperproto.getSize = function () {\n var container = this.canvas.parentNode;\n return {\n width: container.offsetWidth,\n height: container.offsetHeight\n };\n };\n /*\\\n * Paper.setSize\n [ method ]\n **\n * If you need to change dimensions of the canvas call this method\n **\n > Parameters\n **\n - width (number) new width of the canvas\n - height (number) new height of the canvas\n \\*/\n paperproto.setSize = function (width, height) {\n return R._engine.setSize.call(this, width, height);\n };\n /*\\\n * Paper.setViewBox\n [ method ]\n **\n * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by\n * specifying new boundaries.\n **\n > Parameters\n **\n - x (number) new x position, default is `0`\n - y (number) new y position, default is `0`\n - w (number) new width of the canvas\n - h (number) new height of the canvas\n - fit (boolean) `true` if you want graphics to fit into new boundary box\n \\*/\n paperproto.setViewBox = function (x, y, w, h, fit) {\n return R._engine.setViewBox.call(this, x, y, w, h, fit);\n };\n /*\\\n * Paper.top\n [ property ]\n **\n * Points to the topmost element on the paper\n \\*/\n /*\\\n * Paper.bottom\n [ property ]\n **\n * Points to the bottom element on the paper\n \\*/\n paperproto.top = paperproto.bottom = null;\n /*\\\n * Paper.raphael\n [ property ]\n **\n * Points to the @Raphael object/function\n \\*/\n paperproto.raphael = R;\n var getOffset = function (elem) {\n var box = elem.getBoundingClientRect(),\n doc = elem.ownerDocument,\n body = doc.body,\n docElem = doc.documentElement,\n clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,\n top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,\n left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;\n return {\n y: top,\n x: left\n };\n };\n /*\\\n * Paper.getElementByPoint\n [ method ]\n **\n * Returns you topmost element under given point.\n **\n = (object) Raphaël element object\n > Parameters\n **\n - x (number) x coordinate from the top left corner of the window\n - y (number) y coordinate from the top left corner of the window\n > Usage\n | paper.getElementByPoint(mouseX, mouseY).attr({stroke: \"#f00\"});\n \\*/\n paperproto.getElementByPoint = function (x, y) {\n var paper = this,\n svg = paper.canvas,\n target = g.doc.elementFromPoint(x, y);\n if (g.win.opera && target.tagName == \"svg\") {\n var so = getOffset(svg),\n sr = svg.createSVGRect();\n sr.x = x - so.x;\n sr.y = y - so.y;\n sr.width = sr.height = 1;\n var hits = svg.getIntersectionList(sr, null);\n if (hits.length) {\n target = hits[hits.length - 1];\n }\n }\n if (!target) {\n return null;\n }\n while (target.parentNode && target != svg.parentNode && !target.raphael) {\n target = target.parentNode;\n }\n target == paper.canvas.parentNode && (target = svg);\n target = target && target.raphael ? paper.getById(target.raphaelid) : null;\n return target;\n };\n\n /*\\\n * Paper.getElementsByBBox\n [ method ]\n **\n * Returns set of elements that have an intersecting bounding box\n **\n > Parameters\n **\n - bbox (object) bbox to check with\n = (object) @Set\n \\*/\n paperproto.getElementsByBBox = function (bbox) {\n var set = this.set();\n this.forEach(function (el) {\n if (R.isBBoxIntersect(el.getBBox(), bbox)) {\n set.push(el);\n }\n });\n return set;\n };\n\n /*\\\n * Paper.getById\n [ method ]\n **\n * Returns you element by its internal ID.\n **\n > Parameters\n **\n - id (number) id\n = (object) Raphaël element object\n \\*/\n paperproto.getById = function (id) {\n var bot = this.bottom;\n while (bot) {\n if (bot.id == id) {\n return bot;\n }\n bot = bot.next;\n }\n return null;\n };\n /*\\\n * Paper.forEach\n [ method ]\n **\n * Executes given function for each element on the paper\n *\n * If callback function returns `false` it will stop loop running.\n **\n > Parameters\n **\n - callback (function) function to run\n - thisArg (object) context object for the callback\n = (object) Paper object\n > Usage\n | paper.forEach(function (el) {\n | el.attr({ stroke: \"blue\" });\n | });\n \\*/\n paperproto.forEach = function (callback, thisArg) {\n var bot = this.bottom;\n while (bot) {\n if (callback.call(thisArg, bot) === false) {\n return this;\n }\n bot = bot.next;\n }\n return this;\n };\n /*\\\n * Paper.getElementsByPoint\n [ method ]\n **\n * Returns set of elements that have common point inside\n **\n > Parameters\n **\n - x (number) x coordinate of the point\n - y (number) y coordinate of the point\n = (object) @Set\n \\*/\n paperproto.getElementsByPoint = function (x, y) {\n var set = this.set();\n this.forEach(function (el) {\n if (el.isPointInside(x, y)) {\n set.push(el);\n }\n });\n return set;\n };\n function x_y() {\n return this.x + S + this.y;\n }\n function x_y_w_h() {\n return this.x + S + this.y + S + this.width + \" \\xd7 \" + this.height;\n }\n /*\\\n * Element.isPointInside\n [ method ]\n **\n * Determine if given point is inside this element’s shape\n **\n > Parameters\n **\n - x (number) x coordinate of the point\n - y (number) y coordinate of the point\n = (boolean) `true` if point inside the shape\n \\*/\n elproto.isPointInside = function (x, y) {\n var rp = this.realPath = getPath[this.type](this);\n if (this.attr('transform') && this.attr('transform').length) {\n rp = R.transformPath(rp, this.attr('transform'));\n }\n return R.isPointInsidePath(rp, x, y);\n };\n /*\\\n * Element.getBBox\n [ method ]\n **\n * Return bounding box for a given element\n **\n > Parameters\n **\n - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`.\n = (object) Bounding box object:\n o {\n o x: (number) top left corner x\n o y: (number) top left corner y\n o x2: (number) bottom right corner x\n o y2: (number) bottom right corner y\n o width: (number) width\n o height: (number) height\n o }\n \\*/\n elproto.getBBox = function (isWithoutTransform) {\n if (this.removed) {\n return {};\n }\n var _ = this._;\n if (isWithoutTransform) {\n if (_.dirty || !_.bboxwt) {\n this.realPath = getPath[this.type](this);\n _.bboxwt = pathDimensions(this.realPath);\n _.bboxwt.toString = x_y_w_h;\n _.dirty = 0;\n }\n return _.bboxwt;\n }\n if (_.dirty || _.dirtyT || !_.bbox) {\n if (_.dirty || !this.realPath) {\n _.bboxwt = 0;\n this.realPath = getPath[this.type](this);\n }\n _.bbox = pathDimensions(mapPath(this.realPath, this.matrix));\n _.bbox.toString = x_y_w_h;\n _.dirty = _.dirtyT = 0;\n }\n return _.bbox;\n };\n /*\\\n * Element.clone\n [ method ]\n **\n = (object) clone of a given element\n **\n \\*/\n elproto.clone = function () {\n if (this.removed) {\n return null;\n }\n var out = this.paper[this.type]().attr(this.attr());\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Element.glow\n [ method ]\n **\n * Return set of elements that create glow-like effect around given element. See @Paper.set.\n *\n * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself.\n **\n > Parameters\n **\n - glow (object) #optional parameters object with all properties optional:\n o {\n o width (number) size of the glow, default is `10`\n o fill (boolean) will it be filled, default is `false`\n o opacity (number) opacity, default is `0.5`\n o offsetx (number) horizontal offset, default is `0`\n o offsety (number) vertical offset, default is `0`\n o color (string) glow colour, default is `black`\n o }\n = (object) @Paper.set of elements that represents glow\n \\*/\n elproto.glow = function (glow) {\n if (this.type == \"text\") {\n return null;\n }\n glow = glow || {};\n var s = {\n width: (glow.width || 10) + (+this.attr(\"stroke-width\") || 1),\n fill: glow.fill || false,\n opacity: glow.opacity == null ? .5 : glow.opacity,\n offsetx: glow.offsetx || 0,\n offsety: glow.offsety || 0,\n color: glow.color || \"#000\"\n },\n c = s.width / 2,\n r = this.paper,\n out = r.set(),\n path = this.realPath || getPath[this.type](this);\n path = this.matrix ? mapPath(path, this.matrix) : path;\n for (var i = 1; i < c + 1; i++) {\n out.push(r.path(path).attr({\n stroke: s.color,\n fill: s.fill ? s.color : \"none\",\n \"stroke-linejoin\": \"round\",\n \"stroke-linecap\": \"round\",\n \"stroke-width\": +(s.width / c * i).toFixed(3),\n opacity: +(s.opacity / c).toFixed(3)\n }));\n }\n return out.insertBefore(this).translate(s.offsetx, s.offsety);\n };\n var curveslengths = {},\n getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {\n if (length == null) {\n return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);\n } else {\n return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));\n }\n },\n getLengthFactory = function (istotal, subpath) {\n return function (path, length, onlystart) {\n path = path2curve(path);\n var x, y, p, l, sp = \"\", subpaths = {}, point,\n len = 0;\n for (var i = 0, ii = path.length; i < ii; i++) {\n p = path[i];\n if (p[0] == \"M\") {\n x = +p[1];\n y = +p[2];\n } else {\n l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n if (len + l > length) {\n if (subpath && !subpaths.start) {\n point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n sp += [\"C\" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];\n if (onlystart) {return sp;}\n subpaths.start = sp;\n sp = [\"M\" + point.x, point.y + \"C\" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();\n len += l;\n x = +p[5];\n y = +p[6];\n continue;\n }\n if (!istotal && !subpath) {\n point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n return {x: point.x, y: point.y, alpha: point.alpha};\n }\n }\n len += l;\n x = +p[5];\n y = +p[6];\n }\n sp += p.shift() + p;\n }\n subpaths.end = sp;\n point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);\n point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});\n return point;\n };\n };\n var getTotalLength = getLengthFactory(1),\n getPointAtLength = getLengthFactory(),\n getSubpathsAtLength = getLengthFactory(0, 1);\n /*\\\n * Raphael.getTotalLength\n [ method ]\n **\n * Returns length of the given path in pixels.\n **\n > Parameters\n **\n - path (string) SVG path string.\n **\n = (number) length.\n \\*/\n R.getTotalLength = getTotalLength;\n /*\\\n * Raphael.getPointAtLength\n [ method ]\n **\n * Return coordinates of the point located at the given length on the given path.\n **\n > Parameters\n **\n - path (string) SVG path string\n - length (number)\n **\n = (object) representation of the point:\n o {\n o x: (number) x coordinate\n o y: (number) y coordinate\n o alpha: (number) angle of derivative\n o }\n \\*/\n R.getPointAtLength = getPointAtLength;\n /*\\\n * Raphael.getSubpath\n [ method ]\n **\n * Return subpath of a given path from given length to given length.\n **\n > Parameters\n **\n - path (string) SVG path string\n - from (number) position of the start of the segment\n - to (number) position of the end of the segment\n **\n = (string) pathstring for the segment\n \\*/\n R.getSubpath = function (path, from, to) {\n if (this.getTotalLength(path) - to < 1e-6) {\n return getSubpathsAtLength(path, from).end;\n }\n var a = getSubpathsAtLength(path, to, 1);\n return from ? getSubpathsAtLength(a, from).end : a;\n };\n /*\\\n * Element.getTotalLength\n [ method ]\n **\n * Returns length of the path in pixels. Only works for element of “path†type.\n = (number) length.\n \\*/\n elproto.getTotalLength = function () {\n var path = this.getPath();\n if (!path) {\n return;\n }\n\n if (this.node.getTotalLength) {\n return this.node.getTotalLength();\n }\n\n return getTotalLength(path);\n };\n /*\\\n * Element.getPointAtLength\n [ method ]\n **\n * Return coordinates of the point located at the given length on the given path. Only works for element of “path†type.\n **\n > Parameters\n **\n - length (number)\n **\n = (object) representation of the point:\n o {\n o x: (number) x coordinate\n o y: (number) y coordinate\n o alpha: (number) angle of derivative\n o }\n \\*/\n elproto.getPointAtLength = function (length) {\n var path = this.getPath();\n if (!path) {\n return;\n }\n\n return getPointAtLength(path, length);\n };\n /*\\\n * Element.getPath\n [ method ]\n **\n * Returns path of the element. Only works for elements of “path†type and simple elements like circle.\n = (object) path\n **\n \\*/\n elproto.getPath = function () {\n var path,\n getPath = R._getPath[this.type];\n\n if (this.type == \"text\" || this.type == \"set\") {\n return;\n }\n\n if (getPath) {\n path = getPath(this);\n }\n\n return path;\n };\n /*\\\n * Element.getSubpath\n [ method ]\n **\n * Return subpath of a given element from given length to given length. Only works for element of “path†type.\n **\n > Parameters\n **\n - from (number) position of the start of the segment\n - to (number) position of the end of the segment\n **\n = (string) pathstring for the segment\n \\*/\n elproto.getSubpath = function (from, to) {\n var path = this.getPath();\n if (!path) {\n return;\n }\n\n return R.getSubpath(path, from, to);\n };\n /*\\\n * Raphael.easing_formulas\n [ property ]\n **\n * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:\n # \n # “linear†\n # “<†or “easeIn†or “ease-in†\n # “>†or “easeOut†or “ease-out†\n # “<>†or “easeInOut†or “ease-in-out†\n # “backIn†or “back-in†\n # “backOut†or “back-out†\n # “elastic†\n # “bounce†\n # \n # See also Easing demo .
\n \\*/\n var ef = R.easing_formulas = {\n linear: function (n) {\n return n;\n },\n \"<\": function (n) {\n return pow(n, 1.7);\n },\n \">\": function (n) {\n return pow(n, .48);\n },\n \"<>\": function (n) {\n var q = .48 - n / 1.04,\n Q = math.sqrt(.1734 + q * q),\n x = Q - q,\n X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),\n y = -Q - q,\n Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),\n t = X + Y + .5;\n return (1 - t) * 3 * t * t + t * t * t;\n },\n backIn: function (n) {\n var s = 1.70158;\n return n * n * ((s + 1) * n - s);\n },\n backOut: function (n) {\n n = n - 1;\n var s = 1.70158;\n return n * n * ((s + 1) * n + s) + 1;\n },\n elastic: function (n) {\n if (n == !!n) {\n return n;\n }\n return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;\n },\n bounce: function (n) {\n var s = 7.5625,\n p = 2.75,\n l;\n if (n < (1 / p)) {\n l = s * n * n;\n } else {\n if (n < (2 / p)) {\n n -= (1.5 / p);\n l = s * n * n + .75;\n } else {\n if (n < (2.5 / p)) {\n n -= (2.25 / p);\n l = s * n * n + .9375;\n } else {\n n -= (2.625 / p);\n l = s * n * n + .984375;\n }\n }\n }\n return l;\n }\n };\n ef.easeIn = ef[\"ease-in\"] = ef[\"<\"];\n ef.easeOut = ef[\"ease-out\"] = ef[\">\"];\n ef.easeInOut = ef[\"ease-in-out\"] = ef[\"<>\"];\n ef[\"back-in\"] = ef.backIn;\n ef[\"back-out\"] = ef.backOut;\n\n var animationElements = [],\n requestAnimFrame = window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.oRequestAnimationFrame ||\n window.msRequestAnimationFrame ||\n function (callback) {\n setTimeout(callback, 16);\n },\n animation = function () {\n var Now = +new Date,\n l = 0;\n for (; l < animationElements.length; l++) {\n var e = animationElements[l];\n if (e.el.removed || e.paused) {\n continue;\n }\n var time = Now - e.start,\n ms = e.ms,\n easing = e.easing,\n from = e.from,\n diff = e.diff,\n to = e.to,\n t = e.t,\n that = e.el,\n set = {},\n now,\n init = {},\n key;\n if (e.initstatus) {\n time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;\n e.status = e.initstatus;\n delete e.initstatus;\n e.stop && animationElements.splice(l--, 1);\n } else {\n e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;\n }\n if (time < 0) {\n continue;\n }\n if (time < ms) {\n var pos = easing(time / ms);\n for (var attr in from) if (from[has](attr)) {\n switch (availableAnimAttrs[attr]) {\n case nu:\n now = +from[attr] + pos * ms * diff[attr];\n break;\n case \"colour\":\n now = \"rgb(\" + [\n upto255(round(from[attr].r + pos * ms * diff[attr].r)),\n upto255(round(from[attr].g + pos * ms * diff[attr].g)),\n upto255(round(from[attr].b + pos * ms * diff[attr].b))\n ].join(\",\") + \")\";\n break;\n case \"path\":\n now = [];\n for (var i = 0, ii = from[attr].length; i < ii; i++) {\n now[i] = [from[attr][i][0]];\n for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];\n }\n now[i] = now[i].join(S);\n }\n now = now.join(S);\n break;\n case \"transform\":\n if (diff[attr].real) {\n now = [];\n for (i = 0, ii = from[attr].length; i < ii; i++) {\n now[i] = [from[attr][i][0]];\n for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];\n }\n }\n } else {\n var get = function (i) {\n return +from[attr][i] + pos * ms * diff[attr][i];\n };\n // now = [[\"r\", get(2), 0, 0], [\"t\", get(3), get(4)], [\"s\", get(0), get(1), 0, 0]];\n now = [[\"m\", get(0), get(1), get(2), get(3), get(4), get(5)]];\n }\n break;\n case \"csv\":\n if (attr == \"clip-rect\") {\n now = [];\n i = 4;\n while (i--) {\n now[i] = +from[attr][i] + pos * ms * diff[attr][i];\n }\n }\n break;\n default:\n var from2 = [][concat](from[attr]);\n now = [];\n i = that.paper.customAttributes[attr].length;\n while (i--) {\n now[i] = +from2[i] + pos * ms * diff[attr][i];\n }\n break;\n }\n set[attr] = now;\n }\n that.attr(set);\n (function (id, that, anim) {\n setTimeout(function () {\n eve(\"raphael.anim.frame.\" + id, that, anim);\n });\n })(that.id, that, e.anim);\n } else {\n (function(f, el, a) {\n setTimeout(function() {\n eve(\"raphael.anim.frame.\" + el.id, el, a);\n eve(\"raphael.anim.finish.\" + el.id, el, a);\n R.is(f, \"function\") && f.call(el);\n });\n })(e.callback, that, e.anim);\n that.attr(to);\n animationElements.splice(l--, 1);\n if (e.repeat > 1 && !e.next) {\n for (key in to) if (to[has](key)) {\n init[key] = e.totalOrigin[key];\n }\n e.el.attr(init);\n runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);\n }\n if (e.next && !e.stop) {\n runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);\n }\n }\n }\n animationElements.length && requestAnimFrame(animation);\n },\n upto255 = function (color) {\n return color > 255 ? 255 : color < 0 ? 0 : color;\n };\n /*\\\n * Element.animateWith\n [ method ]\n **\n * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element.\n **\n > Parameters\n **\n - el (object) element to sync with\n - anim (object) animation to sync with\n - params (object) #optional final attributes for the element, see also @Element.attr\n - ms (number) #optional number of milliseconds for animation to run\n - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)`\n - callback (function) #optional callback function. Will be called at the end of animation.\n * or\n - element (object) element to sync with\n - anim (object) animation to sync with\n - animation (object) #optional animation object, see @Raphael.animation\n **\n = (object) original element\n \\*/\n elproto.animateWith = function (el, anim, params, ms, easing, callback) {\n var element = this;\n if (element.removed) {\n callback && callback.call(element);\n return element;\n }\n var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback),\n x, y;\n runAnimation(a, element, a.percents[0], null, element.attr());\n for (var i = 0, ii = animationElements.length; i < ii; i++) {\n if (animationElements[i].anim == anim && animationElements[i].el == el) {\n animationElements[ii - 1].start = animationElements[i].start;\n break;\n }\n }\n return element;\n //\n //\n // var a = params ? R.animation(params, ms, easing, callback) : anim,\n // status = element.status(anim);\n // return this.animate(a).status(a, status * anim.ms / a.ms);\n };\n function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {\n var cx = 3 * p1x,\n bx = 3 * (p2x - p1x) - cx,\n ax = 1 - cx - bx,\n cy = 3 * p1y,\n by = 3 * (p2y - p1y) - cy,\n ay = 1 - cy - by;\n function sampleCurveX(t) {\n return ((ax * t + bx) * t + cx) * t;\n }\n function solve(x, epsilon) {\n var t = solveCurveX(x, epsilon);\n return ((ay * t + by) * t + cy) * t;\n }\n function solveCurveX(x, epsilon) {\n var t0, t1, t2, x2, d2, i;\n for(t2 = x, i = 0; i < 8; i++) {\n x2 = sampleCurveX(t2) - x;\n if (abs(x2) < epsilon) {\n return t2;\n }\n d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;\n if (abs(d2) < 1e-6) {\n break;\n }\n t2 = t2 - x2 / d2;\n }\n t0 = 0;\n t1 = 1;\n t2 = x;\n if (t2 < t0) {\n return t0;\n }\n if (t2 > t1) {\n return t1;\n }\n while (t0 < t1) {\n x2 = sampleCurveX(t2);\n if (abs(x2 - x) < epsilon) {\n return t2;\n }\n if (x > x2) {\n t0 = t2;\n } else {\n t1 = t2;\n }\n t2 = (t1 - t0) / 2 + t0;\n }\n return t2;\n }\n return solve(t, 1 / (200 * duration));\n }\n elproto.onAnimation = function (f) {\n f ? eve.on(\"raphael.anim.frame.\" + this.id, f) : eve.unbind(\"raphael.anim.frame.\" + this.id);\n return this;\n };\n function Animation(anim, ms) {\n var percents = [],\n newAnim = {};\n this.ms = ms;\n this.times = 1;\n if (anim) {\n for (var attr in anim) if (anim[has](attr)) {\n newAnim[toFloat(attr)] = anim[attr];\n percents.push(toFloat(attr));\n }\n percents.sort(sortByNumber);\n }\n this.anim = newAnim;\n this.top = percents[percents.length - 1];\n this.percents = percents;\n }\n /*\\\n * Animation.delay\n [ method ]\n **\n * Creates a copy of existing animation object with given delay.\n **\n > Parameters\n **\n - delay (number) number of ms to pass between animation start and actual animation\n **\n = (object) new altered Animation object\n | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3);\n | circle1.animate(anim); // run the given animation immediately\n | circle2.animate(anim.delay(500)); // run the given animation after 500 ms\n \\*/\n Animation.prototype.delay = function (delay) {\n var a = new Animation(this.anim, this.ms);\n a.times = this.times;\n a.del = +delay || 0;\n return a;\n };\n /*\\\n * Animation.repeat\n [ method ]\n **\n * Creates a copy of existing animation object with given repetition.\n **\n > Parameters\n **\n - repeat (number) number iterations of animation. For infinite animation pass `Infinity`\n **\n = (object) new altered Animation object\n \\*/\n Animation.prototype.repeat = function (times) {\n var a = new Animation(this.anim, this.ms);\n a.del = this.del;\n a.times = math.floor(mmax(times, 0)) || 1;\n return a;\n };\n function runAnimation(anim, element, percent, status, totalOrigin, times) {\n percent = toFloat(percent);\n var params,\n isInAnim,\n isInAnimSet,\n percents = [],\n next,\n prev,\n timestamp,\n ms = anim.ms,\n from = {},\n to = {},\n diff = {};\n if (status) {\n for (i = 0, ii = animationElements.length; i < ii; i++) {\n var e = animationElements[i];\n if (e.el.id == element.id && e.anim == anim) {\n if (e.percent != percent) {\n animationElements.splice(i, 1);\n isInAnimSet = 1;\n } else {\n isInAnim = e;\n }\n element.attr(e.totalOrigin);\n break;\n }\n }\n } else {\n status = +to; // NaN\n }\n for (var i = 0, ii = anim.percents.length; i < ii; i++) {\n if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {\n percent = anim.percents[i];\n prev = anim.percents[i - 1] || 0;\n ms = ms / anim.top * (percent - prev);\n next = anim.percents[i + 1];\n params = anim.anim[percent];\n break;\n } else if (status) {\n element.attr(anim.anim[anim.percents[i]]);\n }\n }\n if (!params) {\n return;\n }\n if (!isInAnim) {\n for (var attr in params) if (params[has](attr)) {\n if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {\n from[attr] = element.attr(attr);\n (from[attr] == null) && (from[attr] = availableAttrs[attr]);\n to[attr] = params[attr];\n switch (availableAnimAttrs[attr]) {\n case nu:\n diff[attr] = (to[attr] - from[attr]) / ms;\n break;\n case \"colour\":\n from[attr] = R.getRGB(from[attr]);\n var toColour = R.getRGB(to[attr]);\n diff[attr] = {\n r: (toColour.r - from[attr].r) / ms,\n g: (toColour.g - from[attr].g) / ms,\n b: (toColour.b - from[attr].b) / ms\n };\n break;\n case \"path\":\n var pathes = path2curve(from[attr], to[attr]),\n toPath = pathes[1];\n from[attr] = pathes[0];\n diff[attr] = [];\n for (i = 0, ii = from[attr].length; i < ii; i++) {\n diff[attr][i] = [0];\n for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;\n }\n }\n break;\n case \"transform\":\n var _ = element._,\n eq = equaliseTransform(_[attr], to[attr]);\n if (eq) {\n from[attr] = eq.from;\n to[attr] = eq.to;\n diff[attr] = [];\n diff[attr].real = true;\n for (i = 0, ii = from[attr].length; i < ii; i++) {\n diff[attr][i] = [from[attr][i][0]];\n for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;\n }\n }\n } else {\n var m = (element.matrix || new Matrix),\n to2 = {\n _: {transform: _.transform},\n getBBox: function () {\n return element.getBBox(1);\n }\n };\n from[attr] = [\n m.a,\n m.b,\n m.c,\n m.d,\n m.e,\n m.f\n ];\n extractTransform(to2, to[attr]);\n to[attr] = to2._.transform;\n diff[attr] = [\n (to2.matrix.a - m.a) / ms,\n (to2.matrix.b - m.b) / ms,\n (to2.matrix.c - m.c) / ms,\n (to2.matrix.d - m.d) / ms,\n (to2.matrix.e - m.e) / ms,\n (to2.matrix.f - m.f) / ms\n ];\n // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];\n // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};\n // extractTransform(to2, to[attr]);\n // diff[attr] = [\n // (to2._.sx - _.sx) / ms,\n // (to2._.sy - _.sy) / ms,\n // (to2._.deg - _.deg) / ms,\n // (to2._.dx - _.dx) / ms,\n // (to2._.dy - _.dy) / ms\n // ];\n }\n break;\n case \"csv\":\n var values = Str(params[attr])[split](separator),\n from2 = Str(from[attr])[split](separator);\n if (attr == \"clip-rect\") {\n from[attr] = from2;\n diff[attr] = [];\n i = from2.length;\n while (i--) {\n diff[attr][i] = (values[i] - from[attr][i]) / ms;\n }\n }\n to[attr] = values;\n break;\n default:\n values = [][concat](params[attr]);\n from2 = [][concat](from[attr]);\n diff[attr] = [];\n i = element.paper.customAttributes[attr].length;\n while (i--) {\n diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;\n }\n break;\n }\n }\n }\n var easing = params.easing,\n easyeasy = R.easing_formulas[easing];\n if (!easyeasy) {\n easyeasy = Str(easing).match(bezierrg);\n if (easyeasy && easyeasy.length == 5) {\n var curve = easyeasy;\n easyeasy = function (t) {\n return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);\n };\n } else {\n easyeasy = pipe;\n }\n }\n timestamp = params.start || anim.start || +new Date;\n e = {\n anim: anim,\n percent: percent,\n timestamp: timestamp,\n start: timestamp + (anim.del || 0),\n status: 0,\n initstatus: status || 0,\n stop: false,\n ms: ms,\n easing: easyeasy,\n from: from,\n diff: diff,\n to: to,\n el: element,\n callback: params.callback,\n prev: prev,\n next: next,\n repeat: times || anim.times,\n origin: element.attr(),\n totalOrigin: totalOrigin\n };\n animationElements.push(e);\n if (status && !isInAnim && !isInAnimSet) {\n e.stop = true;\n e.start = new Date - ms * status;\n if (animationElements.length == 1) {\n return animation();\n }\n }\n if (isInAnimSet) {\n e.start = new Date - e.ms * status;\n }\n animationElements.length == 1 && requestAnimFrame(animation);\n } else {\n isInAnim.initstatus = status;\n isInAnim.start = new Date - isInAnim.ms * status;\n }\n eve(\"raphael.anim.start.\" + element.id, element, anim);\n }\n /*\\\n * Raphael.animation\n [ method ]\n **\n * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods.\n * See also @Animation.delay and @Animation.repeat methods.\n **\n > Parameters\n **\n - params (object) final attributes for the element, see also @Element.attr\n - ms (number) number of milliseconds for animation to run\n - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)`\n - callback (function) #optional callback function. Will be called at the end of animation.\n **\n = (object) @Animation\n \\*/\n R.animation = function (params, ms, easing, callback) {\n if (params instanceof Animation) {\n return params;\n }\n if (R.is(easing, \"function\") || !easing) {\n callback = callback || easing || null;\n easing = null;\n }\n params = Object(params);\n ms = +ms || 0;\n var p = {},\n json,\n attr;\n for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + \"%\" != attr) {\n json = true;\n p[attr] = params[attr];\n }\n if (!json) {\n // if percent-like syntax is used and end-of-all animation callback used\n if(callback){\n // find the last one\n var lastKey = 0;\n for(var i in params){\n var percent = toInt(i);\n if(params[has](i) && percent > lastKey){\n lastKey = percent;\n }\n }\n lastKey += '%';\n // if already defined callback in the last keyframe, skip\n !params[lastKey].callback && (params[lastKey].callback = callback);\n }\n return new Animation(params, ms);\n } else {\n easing && (p.easing = easing);\n callback && (p.callback = callback);\n return new Animation({100: p}, ms);\n }\n };\n /*\\\n * Element.animate\n [ method ]\n **\n * Creates and starts animation for given element.\n **\n > Parameters\n **\n - params (object) final attributes for the element, see also @Element.attr\n - ms (number) number of milliseconds for animation to run\n - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)`\n - callback (function) #optional callback function. Will be called at the end of animation.\n * or\n - animation (object) animation object, see @Raphael.animation\n **\n = (object) original element\n \\*/\n elproto.animate = function (params, ms, easing, callback) {\n var element = this;\n if (element.removed) {\n callback && callback.call(element);\n return element;\n }\n var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);\n runAnimation(anim, element, anim.percents[0], null, element.attr());\n return element;\n };\n /*\\\n * Element.setTime\n [ method ]\n **\n * Sets the status of animation of the element in milliseconds. Similar to @Element.status method.\n **\n > Parameters\n **\n - anim (object) animation object\n - value (number) number of milliseconds from the beginning of the animation\n **\n = (object) original element if `value` is specified\n * Note, that during animation following events are triggered:\n *\n * On each animation frame event `anim.frame.`, on start `anim.start.` and on end `anim.finish.`.\n \\*/\n elproto.setTime = function (anim, value) {\n if (anim && value != null) {\n this.status(anim, mmin(value, anim.ms) / anim.ms);\n }\n return this;\n };\n /*\\\n * Element.status\n [ method ]\n **\n * Gets or sets the status of animation of the element.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position.\n **\n = (number) status\n * or\n = (array) status if `anim` is not specified. Array of objects in format:\n o {\n o anim: (object) animation object\n o status: (number) status\n o }\n * or\n = (object) original element if `value` is specified\n \\*/\n elproto.status = function (anim, value) {\n var out = [],\n i = 0,\n len,\n e;\n if (value != null) {\n runAnimation(anim, this, -1, mmin(value, 1));\n return this;\n } else {\n len = animationElements.length;\n for (; i < len; i++) {\n e = animationElements[i];\n if (e.el.id == this.id && (!anim || e.anim == anim)) {\n if (anim) {\n return e.status;\n }\n out.push({\n anim: e.anim,\n status: e.status\n });\n }\n }\n if (anim) {\n return 0;\n }\n return out;\n }\n };\n /*\\\n * Element.pause\n [ method ]\n **\n * Stops animation of the element with ability to resume it later on.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n **\n = (object) original element\n \\*/\n elproto.pause = function (anim) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n if (eve(\"raphael.anim.pause.\" + this.id, this, animationElements[i].anim) !== false) {\n animationElements[i].paused = true;\n }\n }\n return this;\n };\n /*\\\n * Element.resume\n [ method ]\n **\n * Resumes animation if it was paused with @Element.pause method.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n **\n = (object) original element\n \\*/\n elproto.resume = function (anim) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n var e = animationElements[i];\n if (eve(\"raphael.anim.resume.\" + this.id, this, e.anim) !== false) {\n delete e.paused;\n this.status(e.anim, e.status);\n }\n }\n return this;\n };\n /*\\\n * Element.stop\n [ method ]\n **\n * Stops animation of the element.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n **\n = (object) original element\n \\*/\n elproto.stop = function (anim) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n if (eve(\"raphael.anim.stop.\" + this.id, this, animationElements[i].anim) !== false) {\n animationElements.splice(i--, 1);\n }\n }\n return this;\n };\n function stopAnimation(paper) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) {\n animationElements.splice(i--, 1);\n }\n }\n eve.on(\"raphael.remove\", stopAnimation);\n eve.on(\"raphael.clear\", stopAnimation);\n elproto.toString = function () {\n return \"Rapha\\xebl\\u2019s object\";\n };\n\n // Set\n var Set = function (items) {\n this.items = [];\n this.length = 0;\n this.type = \"set\";\n if (items) {\n for (var i = 0, ii = items.length; i < ii; i++) {\n if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {\n this[this.items.length] = this.items[this.items.length] = items[i];\n this.length++;\n }\n }\n }\n },\n setproto = Set.prototype;\n /*\\\n * Set.push\n [ method ]\n **\n * Adds each argument to the current set.\n = (object) original element\n \\*/\n setproto.push = function () {\n var item,\n len;\n for (var i = 0, ii = arguments.length; i < ii; i++) {\n item = arguments[i];\n if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {\n len = this.items.length;\n this[len] = this.items[len] = item;\n this.length++;\n }\n }\n return this;\n };\n /*\\\n * Set.pop\n [ method ]\n **\n * Removes last element and returns it.\n = (object) element\n \\*/\n setproto.pop = function () {\n this.length && delete this[this.length--];\n return this.items.pop();\n };\n /*\\\n * Set.forEach\n [ method ]\n **\n * Executes given function for each element in the set.\n *\n * If function returns `false` it will stop loop running.\n **\n > Parameters\n **\n - callback (function) function to run\n - thisArg (object) context object for the callback\n = (object) Set object\n \\*/\n setproto.forEach = function (callback, thisArg) {\n for (var i = 0, ii = this.items.length; i < ii; i++) {\n if (callback.call(thisArg, this.items[i], i) === false) {\n return this;\n }\n }\n return this;\n };\n for (var method in elproto) if (elproto[has](method)) {\n setproto[method] = (function (methodname) {\n return function () {\n var arg = arguments;\n return this.forEach(function (el) {\n el[methodname][apply](el, arg);\n });\n };\n })(method);\n }\n setproto.attr = function (name, value) {\n if (name && R.is(name, array) && R.is(name[0], \"object\")) {\n for (var j = 0, jj = name.length; j < jj; j++) {\n this.items[j].attr(name[j]);\n }\n } else {\n for (var i = 0, ii = this.items.length; i < ii; i++) {\n this.items[i].attr(name, value);\n }\n }\n return this;\n };\n /*\\\n * Set.clear\n [ method ]\n **\n * Removes all elements from the set\n \\*/\n setproto.clear = function () {\n while (this.length) {\n this.pop();\n }\n };\n /*\\\n * Set.splice\n [ method ]\n **\n * Removes given element from the set\n **\n > Parameters\n **\n - index (number) position of the deletion\n - count (number) number of element to remove\n - insertion… (object) #optional elements to insert\n = (object) set elements that were deleted\n \\*/\n setproto.splice = function (index, count, insertion) {\n index = index < 0 ? mmax(this.length + index, 0) : index;\n count = mmax(0, mmin(this.length - index, count));\n var tail = [],\n todel = [],\n args = [],\n i;\n for (i = 2; i < arguments.length; i++) {\n args.push(arguments[i]);\n }\n for (i = 0; i < count; i++) {\n todel.push(this[index + i]);\n }\n for (; i < this.length - index; i++) {\n tail.push(this[index + i]);\n }\n var arglen = args.length;\n for (i = 0; i < arglen + tail.length; i++) {\n this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];\n }\n i = this.items.length = this.length -= count - arglen;\n while (this[i]) {\n delete this[i++];\n }\n return new Set(todel);\n };\n /*\\\n * Set.exclude\n [ method ]\n **\n * Removes given element from the set\n **\n > Parameters\n **\n - element (object) element to remove\n = (boolean) `true` if object was found & removed from the set\n \\*/\n setproto.exclude = function (el) {\n for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {\n this.splice(i, 1);\n return true;\n }\n };\n setproto.animate = function (params, ms, easing, callback) {\n (R.is(easing, \"function\") || !easing) && (callback = easing || null);\n var len = this.items.length,\n i = len,\n item,\n set = this,\n collector;\n if (!len) {\n return this;\n }\n callback && (collector = function () {\n !--len && callback.call(set);\n });\n easing = R.is(easing, string) ? easing : collector;\n var anim = R.animation(params, ms, easing, collector);\n item = this.items[--i].animate(anim);\n while (i--) {\n this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim);\n (this.items[i] && !this.items[i].removed) || len--;\n }\n return this;\n };\n setproto.insertAfter = function (el) {\n var i = this.items.length;\n while (i--) {\n this.items[i].insertAfter(el);\n }\n return this;\n };\n\n // FREEGROUP Fix: RaphaelJS changes the order of the elements of the 'set' by calling the toBack method.\n // \"toBack\" must be called reverse to care about the rendering order. In this case we override\n // the buggy default implementation here.\n //\n setproto.toBack = function () {\n var i = this.items.length;\n while (i--) {\n this.items[i].toBack();\n }\n return this;\n };\n\n // FREEGROUP Fix: Unfortunately raphael didn'T expose the \"set.prototype\". In this case\n // I must add all extension to the raphael implementation itself.\n // Provide support method for easy check if the elements are visible.\n setproto.isVisible = function () {\n var i = this.items.length;\n var visible = false;\n while (i--) {\n visible = visible ||this.items[i].isVisible();\n }\n return visible;\n };\n\n\n // FREEGROUP FIX: Adding \"isWithoutTransform\" to the function and redirect them to the elements\n setproto.getBBox = function (isWithoutTransform) {\n var x = [],\n y = [],\n x2 = [],\n y2 = [];\n for (var i = this.items.length; i--;) if (!this.items[i].removed) {\n var box = this.items[i].getBBox(isWithoutTransform);\n x.push(box.x);\n y.push(box.y);\n x2.push(box.x + box.width);\n y2.push(box.y + box.height);\n }\n x = mmin[apply](0, x);\n y = mmin[apply](0, y);\n x2 = mmax[apply](0, x2);\n y2 = mmax[apply](0, y2);\n return {\n x: x,\n y: y,\n x2: x2,\n y2: y2,\n width: x2 - x,\n height: y2 - y\n };\n };\n setproto.clone = function (s) {\n s = this.paper.set();\n for (var i = 0, ii = this.items.length; i < ii; i++) {\n s.push(this.items[i].clone());\n }\n return s;\n };\n setproto.toString = function () {\n return \"Rapha\\xebl\\u2018s set\";\n };\n\n setproto.glow = function(glowConfig) {\n var ret = this.paper.set();\n this.forEach(function(shape, index){\n var g = shape.glow(glowConfig);\n if(g != null){\n g.forEach(function(shape2, index2){\n ret.push(shape2);\n });\n }\n });\n return ret;\n };\n\n\n /*\\\n * Set.isPointInside\n [ method ]\n **\n * Determine if given point is inside this set’s elements\n **\n > Parameters\n **\n - x (number) x coordinate of the point\n - y (number) y coordinate of the point\n = (boolean) `true` if point is inside any of the set's elements\n \\*/\n setproto.isPointInside = function (x, y) {\n var isPointInside = false;\n this.forEach(function (el) {\n if (el.isPointInside(x, y)) {\n isPointInside = true;\n return false; // stop loop\n }\n });\n return isPointInside;\n };\n\n /*\\\n * Raphael.registerFont\n [ method ]\n **\n * Adds given font to the registered set of fonts for Raphaël. Should be used as an internal call from within Cufón’s font file.\n * Returns original parameter, so it could be used with chaining.\n # More about Cufón and how to convert your font form TTF, OTF, etc to JavaScript file. \n **\n > Parameters\n **\n - font (object) the font to register\n = (object) the font you passed in\n > Usage\n | Cufon.registerFont(Raphael.registerFont({…}));\n \\*/\n R.registerFont = function (font) {\n if (!font.face) {\n return font;\n }\n this.fonts = this.fonts || {};\n var fontcopy = {\n w: font.w,\n face: {},\n glyphs: {}\n },\n family = font.face[\"font-family\"];\n for (var prop in font.face) if (font.face[has](prop)) {\n fontcopy.face[prop] = font.face[prop];\n }\n if (this.fonts[family]) {\n this.fonts[family].push(fontcopy);\n } else {\n this.fonts[family] = [fontcopy];\n }\n if (!font.svg) {\n fontcopy.face[\"units-per-em\"] = toInt(font.face[\"units-per-em\"], 10);\n for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {\n var path = font.glyphs[glyph];\n fontcopy.glyphs[glyph] = {\n w: path.w,\n k: {},\n d: path.d && \"M\" + path.d.replace(/[mlcxtrv]/g, function (command) {\n return {l: \"L\", c: \"C\", x: \"z\", t: \"m\", r: \"l\", v: \"c\"}[command] || \"M\";\n }) + \"z\"\n };\n if (path.k) {\n for (var k in path.k) if (path[has](k)) {\n fontcopy.glyphs[glyph].k[k] = path.k[k];\n }\n }\n }\n }\n return font;\n };\n /*\\\n * Paper.getFont\n [ method ]\n **\n * Finds font object in the registered fonts by given parameters. You could specify only one word from the font name, like “Myriad†for “Myriad Proâ€.\n **\n > Parameters\n **\n - family (string) font family name or any word from it\n - weight (string) #optional font weight\n - style (string) #optional font style\n - stretch (string) #optional font stretch\n = (object) the font object\n > Usage\n | paper.print(100, 100, \"Test string\", paper.getFont(\"Times\", 800), 30);\n \\*/\n paperproto.getFont = function (family, weight, style, stretch) {\n stretch = stretch || \"normal\";\n style = style || \"normal\";\n weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;\n if (!R.fonts) {\n return;\n }\n var font = R.fonts[family];\n if (!font) {\n var name = new RegExp(\"(^|\\\\s)\" + family.replace(/[^\\w\\d\\s+!~.:_-]/g, E) + \"(\\\\s|$)\", \"i\");\n for (var fontName in R.fonts) if (R.fonts[has](fontName)) {\n if (name.test(fontName)) {\n font = R.fonts[fontName];\n break;\n }\n }\n }\n var thefont;\n if (font) {\n for (var i = 0, ii = font.length; i < ii; i++) {\n thefont = font[i];\n if (thefont.face[\"font-weight\"] == weight && (thefont.face[\"font-style\"] == style || !thefont.face[\"font-style\"]) && thefont.face[\"font-stretch\"] == stretch) {\n break;\n }\n }\n }\n return thefont;\n };\n /*\\\n * Paper.print\n [ method ]\n **\n * Creates path that represent given text written using given font at given position with given size.\n * Result of the method is path element that contains whole text as a separate path.\n **\n > Parameters\n **\n - x (number) x position of the text\n - y (number) y position of the text\n - string (string) text to print\n - font (object) font object, see @Paper.getFont\n - size (number) #optional size of the font, default is `16`\n - origin (string) #optional could be `\"baseline\"` or `\"middle\"`, default is `\"middle\"`\n - letter_spacing (number) #optional number in range `-1..1`, default is `0`\n - line_spacing (number) #optional number in range `1..3`, default is `1`\n = (object) resulting path element, which consist of all letters\n > Usage\n | var txt = r.print(10, 50, \"print\", r.getFont(\"Museo\"), 30).attr({fill: \"#fff\"});\n \\*/\n paperproto.print = function (x, y, string, font, size, origin, letter_spacing, line_spacing) {\n origin = origin || \"middle\"; // baseline|middle\n letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);\n line_spacing = mmax(mmin(line_spacing || 1, 3), 1);\n var letters = Str(string)[split](E),\n shift = 0,\n notfirst = 0,\n path = E,\n scale;\n R.is(font, \"string\") && (font = this.getFont(font));\n if (font) {\n scale = (size || 16) / font.face[\"units-per-em\"];\n var bb = font.face.bbox[split](separator),\n top = +bb[0],\n lineHeight = bb[3] - bb[1],\n shifty = 0,\n height = +bb[1] + (origin == \"baseline\" ? lineHeight + (+font.face.descent) : lineHeight / 2);\n for (var i = 0, ii = letters.length; i < ii; i++) {\n if (letters[i] == \"\\n\") {\n shift = 0;\n curr = 0;\n notfirst = 0;\n shifty += lineHeight * line_spacing;\n } else {\n var prev = notfirst && font.glyphs[letters[i - 1]] || {},\n curr = font.glyphs[letters[i]];\n shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;\n notfirst = 1;\n }\n if (curr && curr.d) {\n path += R.transformPath(curr.d, [\"t\", shift * scale, shifty * scale, \"s\", scale, scale, top, height, \"t\", (x - top) / scale, (y - height) / scale]);\n }\n }\n }\n return this.path(path).attr({\n fill: \"#000\",\n stroke: \"none\"\n });\n };\n\n /*\\\n * Paper.add\n [ method ]\n **\n * Imports elements in JSON array in format `{type: type, }`\n **\n > Parameters\n **\n - json (array)\n = (object) resulting set of imported elements\n > Usage\n | paper.add([\n | {\n | type: \"circle\",\n | cx: 10,\n | cy: 10,\n | r: 5\n | },\n | {\n | type: \"rect\",\n | x: 10,\n | y: 10,\n | width: 10,\n | height: 10,\n | fill: \"#fc0\"\n | }\n | ]);\n \\*/\n paperproto.add = function (json) {\n if (R.is(json, \"array\")) {\n var res = this.set(),\n i = 0,\n ii = json.length,\n j;\n for (; i < ii; i++) {\n j = json[i] || {};\n elements[has](j.type) && res.push(this[j.type]().attr(j));\n }\n }\n return res;\n };\n\n /*\\\n * Raphael.format\n [ method ]\n **\n * Simple format function. Replaces construction of type “`{}`†to the corresponding argument.\n **\n > Parameters\n **\n - token (string) string to format\n - … (string) rest of arguments will be treated as parameters for replacement\n = (string) formated string\n > Usage\n | var x = 10,\n | y = 20,\n | width = 40,\n | height = 50;\n | // this will draw a rectangular shape equivalent to \"M10,20h40v50h-40z\"\n | paper.path(Raphael.format(\"M{0},{1}h{2}v{3}h{4}z\", x, y, width, height, -width));\n \\*/\n R.format = function (token, params) {\n var args = R.is(params, array) ? [0][concat](params) : arguments;\n token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {\n return args[++i] == null ? E : args[i];\n }));\n return token || E;\n };\n /*\\\n * Raphael.fullfill\n [ method ]\n **\n * A little bit more advanced format function than @Raphael.format. Replaces construction of type “`{}`†to the corresponding argument.\n **\n > Parameters\n **\n - token (string) string to format\n - json (object) object which properties will be used as a replacement\n = (string) formated string\n > Usage\n | // this will draw a rectangular shape equivalent to \"M10,20h40v50h-40z\"\n | paper.path(Raphael.fullfill(\"M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z\", {\n | x: 10,\n | y: 20,\n | dim: {\n | width: 40,\n | height: 50,\n | \"negative width\": -40\n | }\n | }));\n \\*/\n R.fullfill = (function () {\n var tokenRegex = /\\{([^\\}]+)\\}/g,\n objNotationRegex = /(?:(?:^|\\.)(.+?)(?=\\[|\\.|$|\\()|\\[('|\")(.+?)\\2\\])(\\(\\))?/g, // matches .xxxxx or [\"xxxxx\"] to run over object properties\n replacer = function (all, key, obj) {\n var res = obj;\n key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {\n name = name || quotedName;\n if (res) {\n if (name in res) {\n res = res[name];\n }\n typeof res == \"function\" && isFunc && (res = res());\n }\n });\n res = (res == null || res == obj ? all : res) + \"\";\n return res;\n };\n return function (str, obj) {\n return String(str).replace(tokenRegex, function (all, key) {\n return replacer(all, key, obj);\n });\n };\n })();\n /*\\\n * Raphael.ninja\n [ method ]\n **\n * If you want to leave no trace of Raphaël (Well, Raphaël creates only one global variable `Raphael`, but anyway.) You can use `ninja` method.\n * Beware, that in this case plugins could stop working, because they are depending on global variable existence.\n **\n = (object) Raphael object\n > Usage\n | (function (local_raphael) {\n | var paper = local_raphael(10, 10, 320, 200);\n | …\n | })(Raphael.ninja());\n \\*/\n R.ninja = function () {\n oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael;\n return R;\n };\n /*\\\n * Raphael.st\n [ property (object) ]\n **\n * You can add your own method to elements and sets. It is wise to add a set method for each element method\n * you added, so you will be able to call the same method on sets too.\n **\n * See also @Raphael.el.\n > Usage\n | Raphael.el.red = function () {\n | this.attr({fill: \"#f00\"});\n | };\n | Raphael.st.red = function () {\n | this.forEach(function (el) {\n | el.red();\n | });\n | };\n | // then use it\n | paper.set(paper.circle(100, 100, 20), paper.circle(110, 100, 20)).red();\n \\*/\n R.st = setproto;\n\n eve.on(\"raphael.DOMload\", function () {\n loaded = true;\n });\n\n // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html\n (function (doc, loaded, f) {\n if (doc.readyState == null && doc.addEventListener){\n doc.addEventListener(loaded, f = function () {\n doc.removeEventListener(loaded, f, false);\n doc.readyState = \"complete\";\n }, false);\n doc.readyState = \"loading\";\n }\n function isLoaded() {\n (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve(\"raphael.DOMload\");\n }\n isLoaded();\n })(document, \"DOMContentLoaded\");\n\n return R;\n}));\n\n// ┌─────────────────────────────────────────────────────────────────────┠\\\\\n// │ Raphaël 2.1.4 - JavaScript Vector Library │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ SVG Module │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\\\\n// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\\\\n// └─────────────────────────────────────────────────────────────────────┘ \\\\\n\n(function (glob, factory) {\n if (typeof define === \"function\" && define.amd) {\n define(\"raphael.svg\", [\"raphael.core\"], function(raphael) {\n return factory(raphael);\n });\n } else if (typeof exports === \"object\") {\n factory(require(\"./raphael.core\"));\n } else {\n factory(glob.Raphael);\n }\n}(this, function(R) {\n if (R && !R.svg) {\n return;\n }\n\n var has = \"hasOwnProperty\",\n Str = String,\n toFloat = parseFloat,\n toInt = parseInt,\n math = Math,\n mmax = math.max,\n abs = math.abs,\n pow = math.pow,\n separator = /[, ]+/,\n eve = R.eve,\n E = \"\",\n S = \" \";\n var xlink = \"http://www.w3.org/1999/xlink\",\n markers = {\n block: \"M5,0 0,2.5 5,5z\",\n classic: \"M5,0 0,2.5 5,5 3.5,3 3.5,2z\",\n diamond: \"M2.5,0 5,2.5 2.5,5 0,2.5z\",\n open: \"M6,1 1,3.5 6,6\",\n oval: \"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z\"\n },\n markerCounter = {};\n R.toString = function () {\n return \"Your browser supports SVG.\\nYou are running Rapha\\xebl \" + this.version;\n };\n var $ = function (el, attr) {\n if (attr) {\n if (typeof el == \"string\") {\n el = $(el);\n }\n for (var key in attr) if (attr[has](key)) {\n if (key.substring(0, 6) == \"xlink:\") {\n el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));\n } else {\n el.setAttribute(key, Str(attr[key]));\n }\n }\n } else {\n el = R._g.doc.createElementNS(\"http://www.w3.org/2000/svg\", el);\n el.style && (el.style.webkitTapHighlightColor = \"rgba(0,0,0,0)\");\n }\n return el;\n },\n addGradientFill = function (element, gradient) {\n var type = \"linear\",\n id = element.id + gradient,\n fx = .5, fy = .5,\n o = element.node,\n SVG = element.paper,\n s = o.style,\n el = R._g.doc.getElementById(id);\n if (!el) {\n gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {\n type = \"radial\";\n if (_fx && _fy) {\n fx = toFloat(_fx);\n fy = toFloat(_fy);\n var dir = ((fy > .5) * 2 - 1);\n pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&\n (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&\n fy != .5 &&\n (fy = fy.toFixed(5) - 1e-5 * dir);\n }\n return E;\n });\n gradient = gradient.split(/\\s*\\-\\s*/);\n if (type == \"linear\") {\n var angle = gradient.shift();\n angle = -toFloat(angle);\n if (isNaN(angle)) {\n return null;\n }\n var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],\n max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);\n vector[2] *= max;\n vector[3] *= max;\n if (vector[2] < 0) {\n vector[0] = -vector[2];\n vector[2] = 0;\n }\n if (vector[3] < 0) {\n vector[1] = -vector[3];\n vector[3] = 0;\n }\n }\n var dots = R._parseDots(gradient);\n if (!dots) {\n return null;\n }\n id = id.replace(/[\\(\\)\\s,\\xb0#]/g, \"_\");\n\n if (element.gradient && id != element.gradient.id) {\n SVG.defs.removeChild(element.gradient);\n delete element.gradient;\n }\n\n if (!element.gradient) {\n el = $(type + \"Gradient\", {id: id});\n element.gradient = el;\n $(el, type == \"radial\" ? {\n fx: fx,\n fy: fy\n } : {\n x1: vector[0],\n y1: vector[1],\n x2: vector[2],\n y2: vector[3],\n gradientTransform: element.matrix.invert()\n });\n SVG.defs.appendChild(el);\n for (var i = 0, ii = dots.length; i < ii; i++) {\n el.appendChild($(\"stop\", {\n offset: dots[i].offset ? dots[i].offset : i ? \"100%\" : \"0%\",\n \"stop-color\": dots[i].color || \"#fff\",\n \"stop-opacity\": isFinite(dots[i].opacity) ? dots[i].opacity : 1\n }));\n }\n }\n }\n /* FREEGROUP: don't push URL parameter into the drawing. This will break Apps with \"?\" in the URL\n * see: https://github.com/DmitryBaranovskiy/raphael/issues/693\n **/\n var url =\"\";//document.location.protocol + \"//\" + document.location.host + document.location.pathname;\n $(o, {\n fill: \"url('\" + url + \"#\" + id + \"')\",\n opacity: 1,\n \"fill-opacity\": 1\n });\n\n s.fill = E;\n s.opacity = 1;\n s.fillOpacity = 1;\n return 1;\n },\n updatePosition = function (o) {\n var bbox = o.getBBox(1);\n $(o.pattern, {patternTransform: o.matrix.invert() + \" translate(\" + bbox.x + \",\" + bbox.y + \")\"});\n },\n addArrow = function (o, value, isEnd) {\n if (o.type == \"path\") {\n var values = Str(value).toLowerCase().split(\"-\"),\n p = o.paper,\n se = isEnd ? \"end\" : \"start\",\n node = o.node,\n attrs = o.attrs,\n stroke = attrs[\"stroke-width\"],\n i = values.length,\n type = \"classic\",\n from,\n to,\n dx,\n refX,\n attr,\n w = 3,\n h = 3,\n t = 5;\n while (i--) {\n switch (values[i]) {\n case \"block\":\n case \"classic\":\n case \"oval\":\n case \"diamond\":\n case \"open\":\n case \"none\":\n type = values[i];\n break;\n case \"wide\": h = 5; break;\n case \"narrow\": h = 2; break;\n case \"long\": w = 5; break;\n case \"short\": w = 2; break;\n }\n }\n if (type == \"open\") {\n w += 2;\n h += 2;\n t += 2;\n dx = 1;\n refX = isEnd ? 4 : 1;\n attr = {\n fill: \"none\",\n stroke: attrs.stroke\n };\n } else {\n refX = dx = w / 2;\n attr = {\n fill: attrs.stroke,\n stroke: \"none\"\n };\n }\n if (o._.arrows) {\n if (isEnd) {\n o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;\n o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;\n } else {\n o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;\n o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;\n }\n } else {\n o._.arrows = {};\n }\n if (type != \"none\") {\n var pathId = \"raphael-marker-\" + type,\n markerId = \"raphael-marker-\" + se + type + w + h + \"-obj\" + o.id;\n if (!R._g.doc.getElementById(pathId)) {\n p.defs.appendChild($($(\"path\"), {\n \"stroke-linecap\": \"round\",\n d: markers[type],\n id: pathId\n }));\n markerCounter[pathId] = 1;\n } else {\n markerCounter[pathId]++;\n }\n var marker = R._g.doc.getElementById(markerId),\n use;\n if (!marker) {\n marker = $($(\"marker\"), {\n id: markerId,\n markerHeight: h,\n markerWidth: w,\n orient: \"auto\",\n refX: refX,\n refY: h / 2\n });\n use = $($(\"use\"), {\n \"xlink:href\": \"#\" + pathId,\n transform: (isEnd ? \"rotate(180 \" + w / 2 + \" \" + h / 2 + \") \" : E) + \"scale(\" + w / t + \",\" + h / t + \")\",\n \"stroke-width\": (1 / ((w / t + h / t) / 2)).toFixed(4)\n });\n marker.appendChild(use);\n p.defs.appendChild(marker);\n markerCounter[markerId] = 1;\n } else {\n markerCounter[markerId]++;\n use = marker.getElementsByTagName(\"use\")[0];\n }\n $(use, attr);\n var delta = dx * (type != \"diamond\" && type != \"oval\");\n if (isEnd) {\n from = o._.arrows.startdx * stroke || 0;\n to = R.getTotalLength(attrs.path) - delta * stroke;\n } else {\n from = delta * stroke;\n to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n }\n attr = {};\n attr[\"marker-\" + se] = \"url(#\" + markerId + \")\";\n if (to || from) {\n attr.d = R.getSubpath(attrs.path, from, to);\n }\n $(node, attr);\n o._.arrows[se + \"Path\"] = pathId;\n o._.arrows[se + \"Marker\"] = markerId;\n o._.arrows[se + \"dx\"] = delta;\n o._.arrows[se + \"Type\"] = type;\n o._.arrows[se + \"String\"] = value;\n } else {\n if (isEnd) {\n from = o._.arrows.startdx * stroke || 0;\n to = R.getTotalLength(attrs.path) - from;\n } else {\n from = 0;\n to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n }\n o._.arrows[se + \"Path\"] && $(node, {d: R.getSubpath(attrs.path, from, to)});\n delete o._.arrows[se + \"Path\"];\n delete o._.arrows[se + \"Marker\"];\n delete o._.arrows[se + \"dx\"];\n delete o._.arrows[se + \"Type\"];\n delete o._.arrows[se + \"String\"];\n }\n for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {\n var item = R._g.doc.getElementById(attr);\n item && item.parentNode.removeChild(item);\n }\n }\n },\n dasharray = {\n \"-\": [3, 1],\n \".\": [1, 1],\n \"-.\": [3, 1, 1, 1],\n \"-..\": [3, 1, 1, 1, 1, 1],\n \". \": [1, 3],\n \"- \": [4, 3],\n \"--\": [8, 3],\n \"- .\": [4, 3, 1, 3],\n \"--.\": [8, 3, 1, 3],\n \"--..\": [8, 3, 1, 3, 1, 3]\n },\n addDashes = function (o, value, params) {\n value = dasharray[Str(value).toLowerCase()];\n if (value) {\n var width = o.attrs[\"stroke-width\"] || \"1\",\n butt = {round: width, square: width, butt: 0}[o.attrs[\"stroke-linecap\"] || params[\"stroke-linecap\"]] || 0,\n dashes = [],\n i = value.length;\n while (i--) {\n dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;\n }\n $(o.node, {\"stroke-dasharray\": dashes.join(\",\")});\n }\n else {\n $(o.node, {\"stroke-dasharray\": \"none\"});\n }\n },\n setFillAndStroke = function (o, params) {\n var node = o.node,\n attrs = o.attrs,\n vis = node.style.visibility;\n node.style.visibility = \"hidden\";\n for (var att in params) {\n if (params[has](att)) {\n if (!R._availableAttrs[has](att)) {\n continue;\n }\n var value = params[att];\n attrs[att] = value;\n switch (att) {\n case \"blur\":\n o.blur(value);\n break;\n case \"title\":\n var title = node.getElementsByTagName(\"title\");\n\n // Use the existing .\n if (title.length && (title = title[0])) {\n title.firstChild.nodeValue = value;\n } else {\n title = $(\"title\");\n var val = R._g.doc.createTextNode(value);\n title.appendChild(val);\n node.appendChild(title);\n }\n break;\n case \"href\":\n case \"target\":\n var pn = node.parentNode;\n if (pn.tagName.toLowerCase() != \"a\") {\n var hl = $(\"a\");\n pn.insertBefore(hl, node);\n hl.appendChild(node);\n pn = hl;\n }\n if (att == \"target\") {\n pn.setAttributeNS(xlink, \"show\", value == \"blank\" ? \"new\" : value);\n } else {\n pn.setAttributeNS(xlink, att, value);\n }\n break;\n case \"cursor\":\n node.style.cursor = value;\n break;\n case \"transform\":\n o.transform(value);\n break;\n case \"arrow-start\":\n addArrow(o, value);\n break;\n case \"arrow-end\":\n addArrow(o, value, 1);\n break;\n case \"clip-rect\":\n var rect = Str(value).split(separator);\n if (rect.length == 4) {\n o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);\n var el = $(\"clipPath\"),\n rc = $(\"rect\");\n el.id = R.createUUID();\n $(rc, {\n x: rect[0],\n y: rect[1],\n width: rect[2],\n height: rect[3]\n });\n el.appendChild(rc);\n o.paper.defs.appendChild(el);\n $(node, {\"clip-path\": \"url(#\" + el.id + \")\"});\n o.clip = rc;\n }\n if (!value) {\n var path = node.getAttribute(\"clip-path\");\n if (path) {\n var clip = R._g.doc.getElementById(path.replace(/(^url\\(#|\\)$)/g, E));\n clip && clip.parentNode.removeChild(clip);\n $(node, {\"clip-path\": E});\n delete o.clip;\n }\n }\n break;\n case \"path\":\n if (o.type == \"path\") {\n $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : \"M0,0\"});\n o._.dirty = 1;\n if (o._.arrows) {\n \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n }\n }\n break;\n case \"width\":\n node.setAttribute(att, value);\n o._.dirty = 1;\n if (attrs.fx) {\n att = \"x\";\n value = attrs.x;\n } else {\n break;\n }\n case \"x\":\n if (attrs.fx) {\n value = -attrs.x - (attrs.width || 0);\n }\n case \"rx\":\n if (att == \"rx\" && o.type == \"rect\") {\n break;\n }\n case \"cx\":\n node.setAttribute(att, value);\n o.pattern && updatePosition(o);\n o._.dirty = 1;\n break;\n case \"height\":\n node.setAttribute(att, value);\n o._.dirty = 1;\n if (attrs.fy) {\n att = \"y\";\n value = attrs.y;\n } else {\n break;\n }\n case \"y\":\n if (attrs.fy) {\n value = -attrs.y - (attrs.height || 0);\n }\n case \"ry\":\n if (att == \"ry\" && o.type == \"rect\") {\n break;\n }\n case \"cy\":\n node.setAttribute(att, value);\n o.pattern && updatePosition(o);\n o._.dirty = 1;\n break;\n case \"r\":\n if (o.type == \"rect\") {\n $(node, {rx: value, ry: value});\n } else {\n node.setAttribute(att, value);\n }\n o._.dirty = 1;\n break;\n case \"src\":\n if (o.type == \"image\") {\n node.setAttributeNS(xlink, \"href\", value);\n }\n break;\n case \"stroke-width\":\n /* FREEGROUP fix\n * draw2d version 3.0.3\n *\n * don't scale the line width if the user resize an shape/element.\n * Obscure stroke-width in case of \"Draw2D touch\" usage\n */\n if(!attrs[\"stroke-scale\"]){\n if (o._.sx != 1 || o._.sy != 1) {\n value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;\n }\n if (o.paper._vbSize) {\n // value *= o.paper._vbSize;\n }\n }\n\n\n node.setAttribute(att, value);\n if (attrs[\"stroke-dasharray\"]) {\n addDashes(o, attrs[\"stroke-dasharray\"], params);\n }\n if (o._.arrows) {\n \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n }\n break;\n case \"stroke-dasharray\":\n addDashes(o, value, params);\n break;\n case \"fill\":\n var isURL = Str(value).match(R._ISURL);\n if (isURL) {\n el = $(\"pattern\");\n var ig = $(\"image\");\n el.id = R.createUUID();\n $(el, {x: 0, y: 0, patternUnits: \"userSpaceOnUse\", height: 1, width: 1});\n $(ig, {x: 0, y: 0, \"xlink:href\": isURL[1]});\n el.appendChild(ig);\n\n (function (el) {\n R._preload(isURL[1], function () {\n var w = this.offsetWidth,\n h = this.offsetHeight;\n $(el, {width: w, height: h});\n $(ig, {width: w, height: h});\n });\n })(el);\n o.paper.defs.appendChild(el);\n $(node, {fill: \"url(#\" + el.id + \")\"});\n o.pattern = el;\n o.pattern && updatePosition(o);\n break;\n }\n var clr = R.getRGB(value);\n if (!clr.error) {\n delete params.gradient;\n delete attrs.gradient;\n !R.is(attrs.opacity, \"undefined\") &&\n R.is(params.opacity, \"undefined\") &&\n $(node, {opacity: attrs.opacity});\n !R.is(attrs[\"fill-opacity\"], \"undefined\") &&\n R.is(params[\"fill-opacity\"], \"undefined\") &&\n $(node, {\"fill-opacity\": attrs[\"fill-opacity\"]});\n } else if ((o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value)) {\n if (\"opacity\" in attrs || \"fill-opacity\" in attrs) {\n var gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n if (gradient) {\n var stops = gradient.getElementsByTagName(\"stop\");\n $(stops[stops.length - 1], {\"stop-opacity\": (\"opacity\" in attrs ? attrs.opacity : 1) * (\"fill-opacity\" in attrs ? attrs[\"fill-opacity\"] : 1)});\n }\n }\n attrs.gradient = value;\n attrs.fill = \"none\";\n break;\n }\n clr[has](\"opacity\") && $(node, {\"fill-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n case \"stroke\":\n clr = R.getRGB(value);\n node.setAttribute(att, clr.hex);\n att == \"stroke\" && clr[has](\"opacity\") && $(node, {\"stroke-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n if (att == \"stroke\" && o._.arrows) {\n \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n }\n break;\n case \"gradient\":\n (o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value);\n break;\n case \"opacity\":\n if (attrs.gradient && !attrs[has](\"stroke-opacity\")) {\n $(node, {\"stroke-opacity\": value > 1 ? value / 100 : value});\n }\n // fall\n case \"fill-opacity\":\n if (attrs.gradient) {\n gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n if (gradient) {\n stops = gradient.getElementsByTagName(\"stop\");\n // FREEGROUP FIX\n for (gri = 0, grii = stops.length; gri < grii; gri++) {\n $(stops[gri], {\"stop-opacity\": value});\n }\n // END FIX\n }\n break;\n }\n default:\n att == \"font-size\" && (value = toInt(value, 10) + \"px\");\n var cssrule = att.replace(/(\\-.)/g, function (w) {\n return w.substring(1).toUpperCase();\n });\n node.style[cssrule] = value;\n o._.dirty = 1;\n node.setAttribute(att, value);\n break;\n }\n }\n }\n\n tuneText(o, params);\n node.style.visibility = vis;\n },\n leading = 1.2,\n tuneText = function (el, params) {\n if (el.type != \"text\" || !(params[has](\"text\") || params[has](\"font\") || params[has](\"font-size\") || params[has](\"x\") || params[has](\"y\"))) {\n return;\n }\n var a = el.attrs,\n node = el.node,\n fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue(\"font-size\"), 10) : 10;\n\n if (params[has](\"text\")) {\n a.text = params.text;\n while (node.firstChild) {\n node.removeChild(node.firstChild);\n }\n var texts = Str(params.text).split(\"\\n\"),\n tspans = [],\n tspan;\n for (var i = 0, ii = texts.length; i < ii; i++) {\n tspan = $(\"tspan\");\n i && $(tspan, {dy: fontSize * leading, x: a.x});\n tspan.appendChild(R._g.doc.createTextNode(texts[i]));\n node.appendChild(tspan);\n tspans[i] = tspan;\n }\n } else {\n tspans = node.getElementsByTagName(\"tspan\");\n for (i = 0, ii = tspans.length; i < ii; i++) if (i) {\n $(tspans[i], {dy: fontSize * leading, x: a.x});\n } else {\n $(tspans[0], {dy: 0});\n }\n }\n $(node, {x: a.x, y: a.y});\n el._.dirty = 1;\n var bb = el._getBBox(),\n dif = a.y - (bb.y + bb.height / 2);\n dif && R.is(dif, \"finite\") && $(tspans[0], {dy: dif});\n },\n getRealNode = function (node) {\n if (node.parentNode && node.parentNode.tagName.toLowerCase() === \"a\") {\n return node.parentNode;\n } else {\n return node;\n }\n },\n Element = function (node, svg) {\n var X = 0,\n Y = 0;\n /*\\\n * Element.node\n [ property (object) ]\n **\n * Gives you a reference to the DOM object, so you can assign event handlers or just mess around.\n **\n * Note: Don’t mess with it.\n > Usage\n | // draw a circle at coordinate 10,10 with radius of 10\n | var c = paper.circle(10, 10, 10);\n | c.node.onclick = function () {\n | c.attr(\"fill\", \"red\");\n | };\n \\*/\n this[0] = this.node = node;\n /*\\\n * Element.raphael\n [ property (object) ]\n **\n * Internal reference to @Raphael object. In case it is not available.\n > Usage\n | Raphael.el.red = function () {\n | var hsb = this.paper.raphael.rgb2hsb(this.attr(\"fill\"));\n | hsb.h = 1;\n | this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex});\n | }\n \\*/\n node.raphael = true;\n /*\\\n * Element.id\n [ property (number) ]\n **\n * Unique id of the element. Especially useful when you want to listen to events of the element,\n * because all events are fired in format `..`. Also useful for @Paper.getById method.\n \\*/\n this.id = R._oid++;\n node.raphaelid = this.id;\n this.matrix = R.matrix();\n this.realPath = null;\n /*\\\n * Element.paper\n [ property (object) ]\n **\n * Internal reference to “paper†where object drawn. Mainly for use in plugins and element extensions.\n > Usage\n | Raphael.el.cross = function () {\n | this.attr({fill: \"red\"});\n | this.paper.path(\"M10,10L50,50M50,10L10,50\")\n | .attr({stroke: \"red\"});\n | }\n \\*/\n this.paper = svg;\n this.attrs = this.attrs || {};\n this._ = {\n transform: [],\n sx: 1,\n sy: 1,\n deg: 0,\n dx: 0,\n dy: 0,\n dirty: 1\n };\n !svg.bottom && (svg.bottom = this);\n /*\\\n * Element.prev\n [ property (object) ]\n **\n * Reference to the previous element in the hierarchy.\n \\*/\n this.prev = svg.top;\n svg.top && (svg.top.next = this);\n svg.top = this;\n /*\\\n * Element.next\n [ property (object) ]\n **\n * Reference to the next element in the hierarchy.\n \\*/\n this.next = null;\n },\n elproto = R.el;\n\n Element.prototype = elproto;\n elproto.constructor = Element;\n\n R._engine.path = function (pathString, SVG) {\n var el = $(\"path\");\n SVG.canvas && SVG.canvas.appendChild(el);\n var p = new Element(el, SVG);\n p.type = \"path\";\n setFillAndStroke(p, {\n fill: \"none\",\n stroke: \"#000\",\n path: pathString\n });\n return p;\n };\n /*\\\n * Element.rotate\n [ method ]\n **\n * Deprecated! Use @Element.transform instead.\n * Adds rotation by given angle around given point to the list of\n * transformations of the element.\n > Parameters\n - deg (number) angle in degrees\n - cx (number) #optional x coordinate of the centre of rotation\n - cy (number) #optional y coordinate of the centre of rotation\n * If cx & cy aren’t specified centre of the shape is used as a point of rotation.\n = (object) @Element\n \\*/\n elproto.rotate = function (deg, cx, cy) {\n if (this.removed) {\n return this;\n }\n deg = Str(deg).split(separator);\n if (deg.length - 1) {\n cx = toFloat(deg[1]);\n cy = toFloat(deg[2]);\n }\n deg = toFloat(deg[0]);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n cx = bbox.x + bbox.width / 2;\n cy = bbox.y + bbox.height / 2;\n }\n this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n return this;\n };\n /*\\\n * Element.scale\n [ method ]\n **\n * Deprecated! Use @Element.transform instead.\n * Adds scale by given amount relative to given point to the list of\n * transformations of the element.\n > Parameters\n - sx (number) horisontal scale amount\n - sy (number) vertical scale amount\n - cx (number) #optional x coordinate of the centre of scale\n - cy (number) #optional y coordinate of the centre of scale\n * If cx & cy aren’t specified centre of the shape is used instead.\n = (object) @Element\n \\*/\n elproto.scale = function (sx, sy, cx, cy) {\n if (this.removed) {\n return this;\n }\n sx = Str(sx).split(separator);\n if (sx.length - 1) {\n sy = toFloat(sx[1]);\n cx = toFloat(sx[2]);\n cy = toFloat(sx[3]);\n }\n sx = toFloat(sx[0]);\n (sy == null) && (sy = sx);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n }\n cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n return this;\n };\n /*\\\n * Element.translate\n [ method ]\n **\n * Deprecated! Use @Element.transform instead.\n * Adds translation by given amount to the list of transformations of the element.\n > Parameters\n - dx (number) horisontal shift\n - dy (number) vertical shift\n = (object) @Element\n \\*/\n elproto.translate = function (dx, dy) {\n if (this.removed) {\n return this;\n }\n dx = Str(dx).split(separator);\n if (dx.length - 1) {\n dy = toFloat(dx[1]);\n }\n dx = toFloat(dx[0]) || 0;\n dy = +dy || 0;\n this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n return this;\n };\n /*\\\n * Element.transform\n [ method ]\n **\n * Adds transformation to the element which is separate to other attributes,\n * i.e. translation doesn’t change `x` or `y` of the rectange. The format\n * of transformation string is similar to the path string syntax:\n | \"t100,100r30,100,100s2,2,100,100r45s1.5\"\n * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for\n * scale and `m` is for matrix.\n *\n * There are also alternative “absolute†translation, rotation and scale: `T`, `R` and `S`. They will not take previous transformation into account. For example, `...T100,0` will always move element 100 px horisontally, while `...t100,0` could move it vertically if there is `r90` before. Just compare results of `r90t100,0` and `r90T100,0`.\n *\n * So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100;\n * rotate 45° around centre; scale 1.5 times relative to centreâ€. As you can see rotate and scale commands have origin\n * coordinates as optional parameters, the default is the centre point of the element.\n * Matrix accepts six parameters.\n > Usage\n | var el = paper.rect(10, 20, 300, 200);\n | // translate 100, 100, rotate 45°, translate -100, 0\n | el.transform(\"t100,100r45t-100,0\");\n | // if you want you can append or prepend transformations\n | el.transform(\"...t50,50\");\n | el.transform(\"s2...\");\n | // or even wrap\n | el.transform(\"t50,50...t-50-50\");\n | // to reset transformation call method with empty string\n | el.transform(\"\");\n | // to get current value call it without parameters\n | console.log(el.transform());\n > Parameters\n - tstr (string) #optional transformation string\n * If tstr isn’t specified\n = (string) current transformation string\n * else\n = (object) @Element\n \\*/\n elproto.transform = function (tstr) {\n var _ = this._;\n if (tstr == null) {\n return _.transform;\n }\n R._extractTransform(this, tstr);\n\n this.clip && $(this.clip, {transform: this.matrix.invert()});\n this.pattern && updatePosition(this);\n this.node && $(this.node, {transform: this.matrix});\n\n if (_.sx != 1 || _.sy != 1) {\n var sw = this.attrs[has](\"stroke-width\") ? this.attrs[\"stroke-width\"] : 1;\n this.attr({\"stroke-width\": sw});\n }\n\n //Reduce transform string\n _.transform = this.matrix.toTransformString();\n\n return this;\n };\n /*\\\n * Element.hide\n [ method ]\n **\n * Makes element invisible. See @Element.show.\n = (object) @Element\n \\*/\n elproto.hide = function () {\n if(!this.removed) this.node.style.display = \"none\";\n return this;\n };\n /*\\\n * Element.show\n [ method ]\n **\n * Makes element visible. See @Element.hide.\n = (object) @Element\n \\*/\n elproto.show = function () {\n if(!this.removed) this.node.style.display = \"\";\n return this;\n };\n /*\\\n * Element.remove\n [ method ]\n **\n * Removes element from the paper.\n \\*/\n elproto.remove = function () {\n var node = getRealNode(this.node);\n if (this.removed || !node.parentNode) {\n return;\n }\n var paper = this.paper;\n paper.__set__ && paper.__set__.exclude(this);\n eve.unbind(\"raphael.*.*.\" + this.id);\n if (this.gradient) {\n paper.defs.removeChild(this.gradient);\n }\n R._tear(this, paper);\n\n node.parentNode.removeChild(node);\n\n // Remove custom data for element\n this.removeData();\n\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n this.removed = true;\n };\n elproto._getBBox = function () {\n if (this.node.style.display == \"none\") {\n this.show();\n var hide = true;\n }\n var canvasHidden = false,\n containerStyle;\n if (this.paper.canvas.parentElement) {\n containerStyle = this.paper.canvas.parentElement.style;\n } //IE10+ can't find parentElement\n else if (this.paper.canvas.parentNode) {\n containerStyle = this.paper.canvas.parentNode.style;\n }\n\n if(containerStyle && containerStyle.display == \"none\") {\n canvasHidden = true;\n containerStyle.display = \"\";\n }\n var bbox = {};\n try {\n bbox = this.node.getBBox();\n } catch(e) {\n // Firefox 3.0.x, 25.0.1 (probably more versions affected) play badly here - possible fix\n bbox = {\n x: this.node.clientLeft,\n y: this.node.clientTop,\n width: this.node.clientWidth,\n height: this.node.clientHeight\n }\n } finally {\n bbox = bbox || {};\n if(canvasHidden){\n containerStyle.display = \"none\";\n }\n }\n hide && this.hide();\n return bbox;\n };\n /*\\\n * Element.attr\n [ method ]\n **\n * Sets the attributes of the element.\n > Parameters\n - attrName (string) attribute’s name\n - value (string) value\n * or\n - params (object) object of name/value pairs\n * or\n - attrName (string) attribute’s name\n * or\n - attrNames (array) in this case method returns array of current values for given attribute names\n = (object) @Element if attrsName & value or params are passed in.\n = (...) value of the attribute if only attrsName is passed in.\n = (array) array of values of the attribute if attrsNames is passed in.\n = (object) object of attributes if nothing is passed in.\n > Possible parameters\n # Please refer to the SVG specification for an explanation of these parameters.
\n o arrow-end (string) arrowhead on the end of the path. The format for string is `[-[-]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `medium`, length: `long`, `short`, `midium`.\n o clip-rect (string) comma or space separated values: x, y, width and height\n o cursor (string) CSS type of the cursor\n o cx (number) the x-axis coordinate of the center of the circle, or ellipse\n o cy (number) the y-axis coordinate of the center of the circle, or ellipse\n o fill (string) colour, gradient or image\n o fill-opacity (number)\n o font (string)\n o font-family (string)\n o font-size (number) font size in pixels\n o font-weight (string)\n o height (number)\n o href (string) URL, if specified element behaves as hyperlink\n o opacity (number)\n o path (string) SVG path string format\n o r (number) radius of the circle, ellipse or rounded corner on the rect\n o rx (number) horisontal radius of the ellipse\n o ry (number) vertical radius of the ellipse\n o src (string) image URL, only works for @Element.image element\n o stroke (string) stroke colour\n o stroke-dasharray (string) [“â€, “noneâ€, “`-`â€, “`.`â€, “`-.`â€, “`-..`â€, “`. `â€, “`- `â€, “`--`â€, “`- .`â€, “`--.`â€, “`--..`â€]\n o stroke-linecap (string) [“`butt`â€, “`square`â€, “`round`â€]\n o stroke-linejoin (string) [“`bevel`â€, “`round`â€, “`miter`â€]\n o stroke-miterlimit (number)\n o stroke-opacity (number)\n o stroke-width (number) stroke width in pixels, default is '1'\n o target (string) used with href\n o text (string) contents of the text element. Use `\\n` for multiline text\n o text-anchor (string) [“`start`â€, “`middle`â€, “`end`â€], default is “`middle`â€\n o title (string) will create tooltip with a given text\n o transform (string) see @Element.transform\n o width (number)\n o x (number)\n o y (number)\n > Gradients\n * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`â€, example: “`90-#fff-#000`†– 90°\n * gradient from white to black or “`0-#fff-#f00:20-#000`†– 0° gradient from white via red (at 20%) to black.\n *\n * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`â€, example: “`r#fff-#000`†–\n * gradient from white to black or “`r(0.25, 0.75)#fff-#000`†– gradient from white to black with focus point\n * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses.\n > Path String\n # Please refer to SVG documentation regarding path string . Raphaël fully supports it.
\n > Colour Parsing\n # \n # Colour name (“red
â€, “green
â€, “cornflowerblue
â€, etc) \n # #••• — shortened HTML colour: (“#000
â€, “#fc0
â€, etc) \n # #•••••• — full length HTML colour: (“#000000
â€, “#bd2300
â€) \n # rgb(•••, •••, •••) — red, green and blue channels’ values: (“rgb(200, 100, 0)
â€) \n # rgb(•••%, •••%, •••%) — same as above, but in %: (“rgb(100%, 175%, 0%)
â€) \n # rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“rgba(200, 100, 0, .5)
â€) \n # rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“rgba(100%, 175%, 0%, 50%)
â€) \n # hsb(•••, •••, •••) — hue, saturation and brightness values: (“hsb(0.5, 0.25, 1)
â€) \n # hsb(•••%, •••%, •••%) — same as above, but in % \n # hsba(•••, •••, •••, •••) — same as above, but with opacity \n # hsl(•••, •••, •••) — almost the same as hsb, see Wikipedia page \n # hsl(•••%, •••%, •••%) — same as above, but in % \n # hsla(•••, •••, •••, •••) — same as above, but with opacity \n # Optionally for hsb and hsl you could specify hue as a degree: “hsl(240deg, 1, .5)
†or, if you want to go fancy, “hsl(240°, 1, .5)
†\n # \n \\*/\n elproto.attr = function (name, value) {\n if (this.removed) {\n return this;\n }\n if (name == null) {\n var res = {};\n for (var a in this.attrs) if (this.attrs[has](a)) {\n res[a] = this.attrs[a];\n }\n res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n res.transform = this._.transform;\n return res;\n }\n if (value == null && R.is(name, \"string\")) {\n if (name == \"fill\" && this.attrs.fill == \"none\" && this.attrs.gradient) {\n return this.attrs.gradient;\n }\n if (name == \"transform\") {\n return this._.transform;\n }\n var names = name.split(separator),\n out = {};\n for (var i = 0, ii = names.length; i < ii; i++) {\n name = names[i];\n if (name in this.attrs) {\n out[name] = this.attrs[name];\n } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n out[name] = this.paper.customAttributes[name].def;\n } else {\n out[name] = R._availableAttrs[name];\n }\n }\n return ii - 1 ? out : out[names[0]];\n }\n if (value == null && R.is(name, \"array\")) {\n out = {};\n for (i = 0, ii = name.length; i < ii; i++) {\n out[name[i]] = this.attr(name[i]);\n }\n return out;\n }\n if (value != null) {\n var params = {};\n params[name] = value;\n } else if (name != null && R.is(name, \"object\")) {\n params = name;\n }\n for (var key in params) {\n eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n }\n for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n this.attrs[key] = params[key];\n for (var subkey in par) if (par[has](subkey)) {\n params[subkey] = par[subkey];\n }\n }\n setFillAndStroke(this, params);\n return this;\n };\n /*\\\n * Element.toFront\n [ method ]\n **\n * Moves the element so it is the closest to the viewer’s eyes, on top of other elements.\n = (object) @Element\n \\*/\n elproto.toFront = function () {\n if (this.removed) {\n return this;\n }\n var node = getRealNode(this.node);\n node.parentNode.appendChild(node);\n var svg = this.paper;\n svg.top != this && R._tofront(this, svg);\n return this;\n };\n /*\\\n * Element.toBack\n [ method ]\n **\n * Moves the element so it is the furthest from the viewer’s eyes, behind other elements.\n = (object) @Element\n \\*/\n elproto.toBack = function () {\n if (this.removed) {\n return this;\n }\n var node = getRealNode(this.node);\n var parentNode = node.parentNode;\n parentNode.insertBefore(node, parentNode.firstChild);\n R._toback(this, this.paper);\n var svg = this.paper;\n return this;\n };\n /*\\\n * Element.insertAfter\n [ method ]\n **\n * Inserts current object after the given one.\n = (object) @Element\n \\*/\n elproto.insertAfter = function (element) {\n if (this.removed || !element) {\n return this;\n }\n\n var node = getRealNode(this.node);\n var afterNode = getRealNode(element.node || element[element.length - 1].node);\n if (afterNode.nextSibling) {\n afterNode.parentNode.insertBefore(node, afterNode.nextSibling);\n } else {\n afterNode.parentNode.appendChild(node);\n }\n R._insertafter(this, element, this.paper);\n return this;\n };\n /*\\\n * Element.insertBefore\n [ method ]\n **\n * Inserts current object before the given one.\n = (object) @Element\n \\*/\n elproto.insertBefore = function (element) {\n if (this.removed || !element) {\n return this;\n }\n\n var node = getRealNode(this.node);\n var beforeNode = getRealNode(element.node || element[0].node);\n beforeNode.parentNode.insertBefore(node, beforeNode);\n R._insertbefore(this, element, this.paper);\n return this;\n };\n elproto.blur = function (size) {\n // Experimental. No Safari support. Use it on your own risk.\n var t = this;\n if (+size !== 0) {\n var fltr = $(\"filter\"),\n blur = $(\"feGaussianBlur\");\n t.attrs.blur = size;\n fltr.id = R.createUUID();\n $(blur, {stdDeviation: +size || 1.5});\n fltr.appendChild(blur);\n t.paper.defs.appendChild(fltr);\n t._blur = fltr;\n $(t.node, {filter: \"url(#\" + fltr.id + \")\"});\n } else {\n if (t._blur) {\n t._blur.parentNode.removeChild(t._blur);\n delete t._blur;\n delete t.attrs.blur;\n }\n t.node.removeAttribute(\"filter\");\n }\n return t;\n };\n R._engine.circle = function (svg, x, y, r) {\n var el = $(\"circle\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {cx: x, cy: y, r: r, fill: \"none\", stroke: \"#000\"};\n res.type = \"circle\";\n $(el, res.attrs);\n return res;\n };\n R._engine.rect = function (svg, x, y, w, h, r) {\n var el = $(\"rect\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {x: x, y: y, width: w, height: h, rx: r || 0, ry: r || 0, fill: \"none\", stroke: \"#000\"};\n res.type = \"rect\";\n $(el, res.attrs);\n return res;\n };\n R._engine.ellipse = function (svg, x, y, rx, ry) {\n var el = $(\"ellipse\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: \"none\", stroke: \"#000\"};\n res.type = \"ellipse\";\n $(el, res.attrs);\n return res;\n };\n R._engine.image = function (svg, src, x, y, w, h) {\n var el = $(\"image\");\n $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: \"none\"});\n el.setAttributeNS(xlink, \"href\", src);\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {x: x, y: y, width: w, height: h, src: src};\n res.type = \"image\";\n return res;\n };\n R._engine.text = function (svg, x, y, text) {\n var el = $(\"text\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {\n x: x,\n y: y,\n \"text-anchor\": \"middle\",\n text: text,\n \"font-family\": R._availableAttrs[\"font-family\"],\n \"font-size\": R._availableAttrs[\"font-size\"],\n stroke: \"none\",\n fill: \"#000\"\n };\n res.type = \"text\";\n setFillAndStroke(res, res.attrs);\n return res;\n };\n R._engine.setSize = function (width, height) {\n this.width = width || this.width;\n this.height = height || this.height;\n this.canvas.setAttribute(\"width\", this.width);\n this.canvas.setAttribute(\"height\", this.height);\n if (this._viewBox) {\n this.setViewBox.apply(this, this._viewBox);\n }\n return this;\n };\n R._engine.create = function () {\n var con = R._getContainer.apply(0, arguments),\n container = con && con.container,\n x = con.x,\n y = con.y,\n width = con.width,\n height = con.height;\n if (!container) {\n throw new Error(\"SVG container not found.\");\n }\n var cnvs = $(\"svg\"),\n css = \"overflow:hidden;\",\n isFloating;\n x = x || 0;\n y = y || 0;\n width = width || 512;\n height = height || 342;\n $(cnvs, {\n height: height,\n version: 1.1,\n width: width,\n xmlns: \"http://www.w3.org/2000/svg\",\n \"xmlns:xlink\": \"http://www.w3.org/1999/xlink\"\n });\n if (container == 1) {\n cnvs.style.cssText = css + \"position:absolute;left:\" + x + \"px;top:\" + y + \"px\";\n R._g.doc.body.appendChild(cnvs);\n isFloating = 1;\n } else {\n cnvs.style.cssText = css + \"position:relative\";\n if (container.firstChild) {\n container.insertBefore(cnvs, container.firstChild);\n } else {\n container.appendChild(cnvs);\n }\n }\n container = new R._Paper;\n container.width = width;\n container.height = height;\n container.canvas = cnvs;\n container.clear();\n container._left = container._top = 0;\n isFloating && (container.renderfix = function () {});\n container.renderfix();\n return container;\n };\n R._engine.setViewBox = function (x, y, w, h, fit) {\n eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n var paperSize = this.getSize(),\n size = mmax(w / paperSize.width, h / paperSize.height),\n top = this.top,\n aspectRatio = fit ? \"xMidYMid meet\" : \"xMinYMin\",\n vb,\n sw;\n if (x == null) {\n if (this._vbSize) {\n size = 1;\n }\n delete this._vbSize;\n vb = \"0 0 \" + this.width + S + this.height;\n } else {\n this._vbSize = size;\n vb = x + S + y + S + w + S + h;\n }\n $(this.canvas, {\n viewBox: vb,\n preserveAspectRatio: aspectRatio\n });\n while (size && top) {\n sw = \"stroke-width\" in top.attrs ? top.attrs[\"stroke-width\"] : 1;\n top.attr({\"stroke-width\": sw});\n top._.dirty = 1;\n top._.dirtyT = 1;\n top = top.prev;\n }\n this._viewBox = [x, y, w, h, !!fit];\n return this;\n };\n /*\\\n * Paper.renderfix\n [ method ]\n **\n * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependant\n * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness.\n * This method fixes the issue.\n **\n Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method.\n \\*/\n R.prototype.renderfix = function () {\n var cnvs = this.canvas,\n s = cnvs.style,\n pos;\n try {\n pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();\n } catch (e) {\n pos = cnvs.createSVGMatrix();\n }\n var left = -pos.e % 1,\n top = -pos.f % 1;\n if (left || top) {\n if (left) {\n this._left = (this._left + left) % 1;\n s.left = this._left + \"px\";\n }\n if (top) {\n this._top = (this._top + top) % 1;\n s.top = this._top + \"px\";\n }\n }\n };\n /*\\\n * Paper.clear\n [ method ]\n **\n * Clears the paper, i.e. removes all the elements.\n \\*/\n R.prototype.clear = function () {\n R.eve(\"raphael.clear\", this);\n var c = this.canvas;\n while (c.firstChild) {\n c.removeChild(c.firstChild);\n }\n this.bottom = this.top = null;\n (this.desc = $(\"desc\")).appendChild(R._g.doc.createTextNode(\"Created with Rapha\\xebl \" + R.version));\n c.appendChild(this.desc);\n c.appendChild(this.defs = $(\"defs\"));\n };\n /*\\\n * Paper.remove\n [ method ]\n **\n * Removes the paper from the DOM.\n \\*/\n R.prototype.remove = function () {\n eve(\"raphael.remove\", this);\n this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n };\n var setproto = R.st;\n for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n setproto[method] = (function (methodname) {\n return function () {\n var arg = arguments;\n return this.forEach(function (el) {\n el[methodname].apply(el, arg);\n });\n };\n })(method);\n }\n}));\n\n// ┌─────────────────────────────────────────────────────────────────────┠\\\\\n// │ Raphaël 2.1.4 - JavaScript Vector Library │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ VML Module │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\\\\n// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\\\\n// └─────────────────────────────────────────────────────────────────────┘ \\\\\n\n(function (glob, factory) {\n if (typeof define === \"function\" && define.amd) {\n define(\"raphael.vml\", [\"raphael.core\"], function(raphael) {\n return factory(raphael);\n });\n } else if (typeof exports === \"object\") {\n factory(require(\"./raphael.core\"));\n } else {\n factory(glob.Raphael);\n }\n}(this, function(R) {\n if (R && !R.vml) {\n return;\n }\n\n var has = \"hasOwnProperty\",\n Str = String,\n toFloat = parseFloat,\n math = Math,\n round = math.round,\n mmax = math.max,\n mmin = math.min,\n abs = math.abs,\n fillString = \"fill\",\n separator = /[, ]+/,\n eve = R.eve,\n ms = \" progid:DXImageTransform.Microsoft\",\n S = \" \",\n E = \"\",\n map = {M: \"m\", L: \"l\", C: \"c\", Z: \"x\", m: \"t\", l: \"r\", c: \"v\", z: \"x\"},\n bites = /([clmz]),?([^clmz]*)/gi,\n blurregexp = / progid:\\S+Blur\\([^\\)]+\\)/g,\n val = /-?[^,\\s-]+/g,\n cssDot = \"position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)\",\n zoom = 21600,\n pathTypes = {path: 1, rect: 1, image: 1},\n ovalTypes = {circle: 1, ellipse: 1},\n path2vml = function (path) {\n var total = /[ahqstv]/ig,\n command = R._pathToAbsolute;\n Str(path).match(total) && (command = R._path2curve);\n total = /[clmz]/g;\n if (command == R._pathToAbsolute && !Str(path).match(total)) {\n var res = Str(path).replace(bites, function (all, command, args) {\n var vals = [],\n isMove = command.toLowerCase() == \"m\",\n res = map[command];\n args.replace(val, function (value) {\n if (isMove && vals.length == 2) {\n res += vals + map[command == \"m\" ? \"l\" : \"L\"];\n vals = [];\n }\n vals.push(round(value * zoom));\n });\n return res + vals;\n });\n return res;\n }\n var pa = command(path), p, r;\n res = [];\n for (var i = 0, ii = pa.length; i < ii; i++) {\n p = pa[i];\n r = pa[i][0].toLowerCase();\n r == \"z\" && (r = \"x\");\n for (var j = 1, jj = p.length; j < jj; j++) {\n r += round(p[j] * zoom) + (j != jj - 1 ? \",\" : E);\n }\n res.push(r);\n }\n return res.join(S);\n },\n compensation = function (deg, dx, dy) {\n var m = R.matrix();\n m.rotate(-deg, .5, .5);\n return {\n dx: m.x(dx, dy),\n dy: m.y(dx, dy)\n };\n },\n setCoords = function (p, sx, sy, dx, dy, deg) {\n var _ = p._,\n m = p.matrix,\n fillpos = _.fillpos,\n o = p.node,\n s = o.style,\n y = 1,\n flip = \"\",\n dxdy,\n kx = zoom / sx,\n ky = zoom / sy;\n s.visibility = \"hidden\";\n if (!sx || !sy) {\n return;\n }\n o.coordsize = abs(kx) + S + abs(ky);\n s.rotation = deg * (sx * sy < 0 ? -1 : 1);\n if (deg) {\n var c = compensation(deg, dx, dy);\n dx = c.dx;\n dy = c.dy;\n }\n sx < 0 && (flip += \"x\");\n sy < 0 && (flip += \" y\") && (y = -1);\n s.flip = flip;\n o.coordorigin = (dx * -kx) + S + (dy * -ky);\n if (fillpos || _.fillsize) {\n var fill = o.getElementsByTagName(fillString);\n fill = fill && fill[0];\n o.removeChild(fill);\n if (fillpos) {\n c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));\n fill.position = c.dx * y + S + c.dy * y;\n }\n if (_.fillsize) {\n fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);\n }\n o.appendChild(fill);\n }\n s.visibility = \"visible\";\n };\n R.toString = function () {\n return \"Your browser doesn\\u2019t support SVG. Falling down to VML.\\nYou are running Rapha\\xebl \" + this.version;\n };\n var addArrow = function (o, value, isEnd) {\n var values = Str(value).toLowerCase().split(\"-\"),\n se = isEnd ? \"end\" : \"start\",\n i = values.length,\n type = \"classic\",\n w = \"medium\",\n h = \"medium\";\n while (i--) {\n switch (values[i]) {\n case \"block\":\n case \"classic\":\n case \"oval\":\n case \"diamond\":\n case \"open\":\n case \"none\":\n type = values[i];\n break;\n case \"wide\":\n case \"narrow\": h = values[i]; break;\n case \"long\":\n case \"short\": w = values[i]; break;\n }\n }\n var stroke = o.node.getElementsByTagName(\"stroke\")[0];\n stroke[se + \"arrow\"] = type;\n stroke[se + \"arrowlength\"] = w;\n stroke[se + \"arrowwidth\"] = h;\n },\n setFillAndStroke = function (o, params) {\n // o.paper.canvas.style.display = \"none\";\n o.attrs = o.attrs || {};\n var node = o.node,\n a = o.attrs,\n s = node.style,\n xy,\n newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),\n isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),\n res = o;\n\n\n for (var par in params) if (params[has](par)) {\n a[par] = params[par];\n }\n if (newpath) {\n a.path = R._getPath[o.type](o);\n o._.dirty = 1;\n }\n params.href && (node.href = params.href);\n params.title && (node.title = params.title);\n params.target && (node.target = params.target);\n params.cursor && (s.cursor = params.cursor);\n \"blur\" in params && o.blur(params.blur);\n if (params.path && o.type == \"path\" || newpath) {\n node.path = path2vml(~Str(a.path).toLowerCase().indexOf(\"r\") ? R._pathToAbsolute(a.path) : a.path);\n o._.dirty = 1;\n if (o.type == \"image\") {\n o._.fillpos = [a.x, a.y];\n o._.fillsize = [a.width, a.height];\n setCoords(o, 1, 1, 0, 0, 0);\n }\n }\n \"transform\" in params && o.transform(params.transform);\n if (isOval) {\n var cx = +a.cx,\n cy = +a.cy,\n rx = +a.rx || +a.r || 0,\n ry = +a.ry || +a.r || 0;\n node.path = R.format(\"ar{0},{1},{2},{3},{4},{1},{4},{1}x\", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));\n o._.dirty = 1;\n }\n if (\"clip-rect\" in params) {\n var rect = Str(params[\"clip-rect\"]).split(separator);\n if (rect.length == 4) {\n rect[2] = +rect[2] + (+rect[0]);\n rect[3] = +rect[3] + (+rect[1]);\n var div = node.clipRect || R._g.doc.createElement(\"div\"),\n dstyle = div.style;\n dstyle.clip = R.format(\"rect({1}px {2}px {3}px {0}px)\", rect);\n if (!node.clipRect) {\n dstyle.position = \"absolute\";\n dstyle.top = 0;\n dstyle.left = 0;\n dstyle.width = o.paper.width + \"px\";\n dstyle.height = o.paper.height + \"px\";\n node.parentNode.insertBefore(div, node);\n div.appendChild(node);\n node.clipRect = div;\n }\n }\n if (!params[\"clip-rect\"]) {\n node.clipRect && (node.clipRect.style.clip = \"auto\");\n }\n }\n if (o.textpath) {\n var textpathStyle = o.textpath.style;\n params.font && (textpathStyle.font = params.font);\n params[\"font-family\"] && (textpathStyle.fontFamily = '\"' + params[\"font-family\"].split(\",\")[0].replace(/^['\"]+|['\"]+$/g, E) + '\"');\n params[\"font-size\"] && (textpathStyle.fontSize = params[\"font-size\"]);\n params[\"font-weight\"] && (textpathStyle.fontWeight = params[\"font-weight\"]);\n params[\"font-style\"] && (textpathStyle.fontStyle = params[\"font-style\"]);\n }\n if (\"arrow-start\" in params) {\n addArrow(res, params[\"arrow-start\"]);\n }\n if (\"arrow-end\" in params) {\n addArrow(res, params[\"arrow-end\"], 1);\n }\n if (params.opacity != null ||\n params[\"stroke-width\"] != null ||\n params.fill != null ||\n params.src != null ||\n params.stroke != null ||\n params[\"stroke-width\"] != null ||\n params[\"stroke-opacity\"] != null ||\n params[\"fill-opacity\"] != null ||\n params[\"stroke-dasharray\"] != null ||\n params[\"stroke-miterlimit\"] != null ||\n params[\"stroke-linejoin\"] != null ||\n params[\"stroke-linecap\"] != null) {\n var fill = node.getElementsByTagName(fillString),\n newfill = false;\n fill = fill && fill[0];\n !fill && (newfill = fill = createNode(fillString));\n if (o.type == \"image\" && params.src) {\n fill.src = params.src;\n }\n params.fill && (fill.on = true);\n if (fill.on == null || params.fill == \"none\" || params.fill === null) {\n fill.on = false;\n }\n if (fill.on && params.fill) {\n var isURL = Str(params.fill).match(R._ISURL);\n if (isURL) {\n fill.parentNode == node && node.removeChild(fill);\n fill.rotate = true;\n fill.src = isURL[1];\n fill.type = \"tile\";\n var bbox = o.getBBox(1);\n fill.position = bbox.x + S + bbox.y;\n o._.fillpos = [bbox.x, bbox.y];\n\n R._preload(isURL[1], function () {\n o._.fillsize = [this.offsetWidth, this.offsetHeight];\n });\n } else {\n fill.color = R.getRGB(params.fill).hex;\n fill.src = E;\n fill.type = \"solid\";\n if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != \"r\") && addGradientFill(res, params.fill, fill)) {\n a.fill = \"none\";\n a.gradient = params.fill;\n fill.rotate = false;\n }\n }\n }\n if (\"fill-opacity\" in params || \"opacity\" in params) {\n var opacity = ((+a[\"fill-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);\n opacity = mmin(mmax(opacity, 0), 1);\n fill.opacity = opacity;\n if (fill.src) {\n fill.color = \"none\";\n }\n }\n node.appendChild(fill);\n var stroke = (node.getElementsByTagName(\"stroke\") && node.getElementsByTagName(\"stroke\")[0]),\n newstroke = false;\n !stroke && (newstroke = stroke = createNode(\"stroke\"));\n if ((params.stroke && params.stroke != \"none\") ||\n params[\"stroke-width\"] ||\n params[\"stroke-opacity\"] != null ||\n params[\"stroke-dasharray\"] ||\n params[\"stroke-miterlimit\"] ||\n params[\"stroke-linejoin\"] ||\n params[\"stroke-linecap\"]) {\n stroke.on = true;\n }\n (params.stroke == \"none\" || params.stroke === null || stroke.on == null || params.stroke == 0 || params[\"stroke-width\"] == 0) && (stroke.on = false);\n var strokeColor = R.getRGB(params.stroke);\n stroke.on && params.stroke && (stroke.color = strokeColor.hex);\n opacity = ((+a[\"stroke-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);\n var width = (toFloat(params[\"stroke-width\"]) || 1) * .75;\n opacity = mmin(mmax(opacity, 0), 1);\n params[\"stroke-width\"] == null && (width = a[\"stroke-width\"]);\n params[\"stroke-width\"] && (stroke.weight = width);\n width && width < 1 && (opacity *= width) && (stroke.weight = 1);\n stroke.opacity = opacity;\n\n params[\"stroke-linejoin\"] && (stroke.joinstyle = params[\"stroke-linejoin\"] || \"miter\");\n stroke.miterlimit = params[\"stroke-miterlimit\"] || 8;\n params[\"stroke-linecap\"] && (stroke.endcap = params[\"stroke-linecap\"] == \"butt\" ? \"flat\" : params[\"stroke-linecap\"] == \"square\" ? \"square\" : \"round\");\n if (\"stroke-dasharray\" in params) {\n var dasharray = {\n \"-\": \"shortdash\",\n \".\": \"shortdot\",\n \"-.\": \"shortdashdot\",\n \"-..\": \"shortdashdotdot\",\n \". \": \"dot\",\n \"- \": \"dash\",\n \"--\": \"longdash\",\n \"- .\": \"dashdot\",\n \"--.\": \"longdashdot\",\n \"--..\": \"longdashdotdot\"\n };\n stroke.dashstyle = dasharray[has](params[\"stroke-dasharray\"]) ? dasharray[params[\"stroke-dasharray\"]] : E;\n }\n newstroke && node.appendChild(stroke);\n }\n if (res.type == \"text\") {\n res.paper.canvas.style.display = E;\n var span = res.paper.span,\n m = 100,\n fontSize = a.font && a.font.match(/\\d+(?:\\.\\d*)?(?=px)/);\n s = span.style;\n a.font && (s.font = a.font);\n a[\"font-family\"] && (s.fontFamily = a[\"font-family\"]);\n a[\"font-weight\"] && (s.fontWeight = a[\"font-weight\"]);\n a[\"font-style\"] && (s.fontStyle = a[\"font-style\"]);\n fontSize = toFloat(a[\"font-size\"] || fontSize && fontSize[0]) || 10;\n s.fontSize = fontSize * m + \"px\";\n res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/\"));\n var brect = span.getBoundingClientRect();\n res.W = a.w = (brect.right - brect.left) / m;\n res.H = a.h = (brect.bottom - brect.top) / m;\n // res.paper.canvas.style.display = \"none\";\n res.X = a.x;\n res.Y = a.y + res.H / 2;\n\n (\"x\" in params || \"y\" in params) && (res.path.v = R.format(\"m{0},{1}l{2},{1}\", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));\n var dirtyattrs = [\"x\", \"y\", \"text\", \"font\", \"font-family\", \"font-weight\", \"font-style\", \"font-size\"];\n for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {\n res._.dirty = 1;\n break;\n }\n\n // text-anchor emulation\n switch (a[\"text-anchor\"]) {\n case \"start\":\n res.textpath.style[\"v-text-align\"] = \"left\";\n res.bbx = res.W / 2;\n break;\n case \"end\":\n res.textpath.style[\"v-text-align\"] = \"right\";\n res.bbx = -res.W / 2;\n break;\n default:\n res.textpath.style[\"v-text-align\"] = \"center\";\n res.bbx = 0;\n break;\n }\n res.textpath.style[\"v-text-kern\"] = true;\n }\n // res.paper.canvas.style.display = E;\n },\n addGradientFill = function (o, gradient, fill) {\n o.attrs = o.attrs || {};\n var attrs = o.attrs,\n pow = Math.pow,\n opacity,\n oindex,\n type = \"linear\",\n fxfy = \".5 .5\";\n o.attrs.gradient = gradient;\n gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {\n type = \"radial\";\n if (fx && fy) {\n fx = toFloat(fx);\n fy = toFloat(fy);\n pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);\n fxfy = fx + S + fy;\n }\n return E;\n });\n gradient = gradient.split(/\\s*\\-\\s*/);\n if (type == \"linear\") {\n var angle = gradient.shift();\n angle = -toFloat(angle);\n if (isNaN(angle)) {\n return null;\n }\n }\n var dots = R._parseDots(gradient);\n if (!dots) {\n return null;\n }\n o = o.shape || o.node;\n if (dots.length) {\n o.removeChild(fill);\n fill.on = true;\n fill.method = \"none\";\n fill.color = dots[0].color;\n fill.color2 = dots[dots.length - 1].color;\n var clrs = [];\n for (var i = 0, ii = dots.length; i < ii; i++) {\n dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);\n }\n fill.colors = clrs.length ? clrs.join() : \"0% \" + fill.color;\n if (type == \"radial\") {\n fill.type = \"gradientTitle\";\n fill.focus = \"100%\";\n fill.focussize = \"0 0\";\n fill.focusposition = fxfy;\n fill.angle = 0;\n } else {\n // fill.rotate= true;\n fill.type = \"gradient\";\n fill.angle = (270 - angle) % 360;\n }\n o.appendChild(fill);\n }\n return 1;\n },\n Element = function (node, vml) {\n this[0] = this.node = node;\n node.raphael = true;\n this.id = R._oid++;\n node.raphaelid = this.id;\n this.X = 0;\n this.Y = 0;\n this.attrs = {};\n this.paper = vml;\n this.matrix = R.matrix();\n this._ = {\n transform: [],\n sx: 1,\n sy: 1,\n dx: 0,\n dy: 0,\n deg: 0,\n dirty: 1,\n dirtyT: 1\n };\n !vml.bottom && (vml.bottom = this);\n this.prev = vml.top;\n vml.top && (vml.top.next = this);\n vml.top = this;\n this.next = null;\n };\n var elproto = R.el;\n\n Element.prototype = elproto;\n elproto.constructor = Element;\n elproto.transform = function (tstr) {\n if (tstr == null) {\n return this._.transform;\n }\n var vbs = this.paper._viewBoxShift,\n vbt = vbs ? \"s\" + [vbs.scale, vbs.scale] + \"-1-1t\" + [vbs.dx, vbs.dy] : E,\n oldt;\n if (vbs) {\n oldt = tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, this._.transform || E);\n }\n R._extractTransform(this, vbt + tstr);\n var matrix = this.matrix.clone(),\n skew = this.skew,\n o = this.node,\n split,\n isGrad = ~Str(this.attrs.fill).indexOf(\"-\"),\n isPatt = !Str(this.attrs.fill).indexOf(\"url(\");\n matrix.translate(1, 1);\n if (isPatt || isGrad || this.type == \"image\") {\n skew.matrix = \"1 0 0 1\";\n skew.offset = \"0 0\";\n split = matrix.split();\n if ((isGrad && split.noRotation) || !split.isSimple) {\n o.style.filter = matrix.toFilter();\n var bb = this.getBBox(),\n bbt = this.getBBox(1),\n dx = bb.x - bbt.x,\n dy = bb.y - bbt.y;\n o.coordorigin = (dx * -zoom) + S + (dy * -zoom);\n setCoords(this, 1, 1, dx, dy, 0);\n } else {\n o.style.filter = E;\n setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);\n }\n } else {\n o.style.filter = E;\n skew.matrix = Str(matrix);\n skew.offset = matrix.offset();\n }\n if (oldt !== null) { // empty string value is true as well\n this._.transform = oldt;\n R._extractTransform(this, oldt);\n }\n return this;\n };\n elproto.rotate = function (deg, cx, cy) {\n if (this.removed) {\n return this;\n }\n if (deg == null) {\n return;\n }\n deg = Str(deg).split(separator);\n if (deg.length - 1) {\n cx = toFloat(deg[1]);\n cy = toFloat(deg[2]);\n }\n deg = toFloat(deg[0]);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n cx = bbox.x + bbox.width / 2;\n cy = bbox.y + bbox.height / 2;\n }\n this._.dirtyT = 1;\n this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n return this;\n };\n elproto.translate = function (dx, dy) {\n if (this.removed) {\n return this;\n }\n dx = Str(dx).split(separator);\n if (dx.length - 1) {\n dy = toFloat(dx[1]);\n }\n dx = toFloat(dx[0]) || 0;\n dy = +dy || 0;\n if (this._.bbox) {\n this._.bbox.x += dx;\n this._.bbox.y += dy;\n }\n this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n return this;\n };\n elproto.scale = function (sx, sy, cx, cy) {\n if (this.removed) {\n return this;\n }\n sx = Str(sx).split(separator);\n if (sx.length - 1) {\n sy = toFloat(sx[1]);\n cx = toFloat(sx[2]);\n cy = toFloat(sx[3]);\n isNaN(cx) && (cx = null);\n isNaN(cy) && (cy = null);\n }\n sx = toFloat(sx[0]);\n (sy == null) && (sy = sx);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n }\n cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n\n this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n this._.dirtyT = 1;\n return this;\n };\n elproto.hide = function () {\n !this.removed && (this.node.style.display = \"none\");\n return this;\n };\n elproto.show = function () {\n !this.removed && (this.node.style.display = E);\n return this;\n };\n // Needed to fix the vml setViewBox issues\n elproto.auxGetBBox = R.el.getBBox;\n elproto.getBBox = function(){\n var b = this.auxGetBBox();\n if (this.paper && this.paper._viewBoxShift)\n {\n var c = {};\n var z = 1/this.paper._viewBoxShift.scale;\n c.x = b.x - this.paper._viewBoxShift.dx;\n c.x *= z;\n c.y = b.y - this.paper._viewBoxShift.dy;\n c.y *= z;\n c.width = b.width * z;\n c.height = b.height * z;\n c.x2 = c.x + c.width;\n c.y2 = c.y + c.height;\n return c;\n }\n return b;\n };\n elproto._getBBox = function () {\n if (this.removed) {\n return {};\n }\n return {\n x: this.X + (this.bbx || 0) - this.W / 2,\n y: this.Y - this.H,\n width: this.W,\n height: this.H\n };\n };\n elproto.remove = function () {\n if (this.removed || !this.node.parentNode) {\n return;\n }\n this.paper.__set__ && this.paper.__set__.exclude(this);\n R.eve.unbind(\"raphael.*.*.\" + this.id);\n R._tear(this, this.paper);\n this.node.parentNode.removeChild(this.node);\n this.shape && this.shape.parentNode.removeChild(this.shape);\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n this.removed = true;\n };\n elproto.attr = function (name, value) {\n if (this.removed) {\n return this;\n }\n if (name == null) {\n var res = {};\n for (var a in this.attrs) if (this.attrs[has](a)) {\n res[a] = this.attrs[a];\n }\n res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n res.transform = this._.transform;\n return res;\n }\n if (value == null && R.is(name, \"string\")) {\n if (name == fillString && this.attrs.fill == \"none\" && this.attrs.gradient) {\n return this.attrs.gradient;\n }\n var names = name.split(separator),\n out = {};\n for (var i = 0, ii = names.length; i < ii; i++) {\n name = names[i];\n if (name in this.attrs) {\n out[name] = this.attrs[name];\n } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n out[name] = this.paper.customAttributes[name].def;\n } else {\n out[name] = R._availableAttrs[name];\n }\n }\n return ii - 1 ? out : out[names[0]];\n }\n if (this.attrs && value == null && R.is(name, \"array\")) {\n out = {};\n for (i = 0, ii = name.length; i < ii; i++) {\n out[name[i]] = this.attr(name[i]);\n }\n return out;\n }\n var params;\n if (value != null) {\n params = {};\n params[name] = value;\n }\n value == null && R.is(name, \"object\") && (params = name);\n for (var key in params) {\n eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n }\n if (params) {\n for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n this.attrs[key] = params[key];\n for (var subkey in par) if (par[has](subkey)) {\n params[subkey] = par[subkey];\n }\n }\n // this.paper.canvas.style.display = \"none\";\n if (params.text && this.type == \"text\") {\n this.textpath.string = params.text;\n }\n setFillAndStroke(this, params);\n // this.paper.canvas.style.display = E;\n }\n return this;\n };\n elproto.toFront = function () {\n !this.removed && this.node.parentNode.appendChild(this.node);\n this.paper && this.paper.top != this && R._tofront(this, this.paper);\n return this;\n };\n elproto.toBack = function () {\n if (this.removed) {\n return this;\n }\n if (this.node.parentNode.firstChild != this.node) {\n this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);\n R._toback(this, this.paper);\n }\n return this;\n };\n elproto.insertAfter = function (element) {\n if (this.removed) {\n return this;\n }\n if (element.constructor == R.st.constructor) {\n element = element[element.length - 1];\n }\n if (element.node.nextSibling) {\n element.node.parentNode.insertBefore(this.node, element.node.nextSibling);\n } else {\n element.node.parentNode.appendChild(this.node);\n }\n R._insertafter(this, element, this.paper);\n return this;\n };\n elproto.insertBefore = function (element) {\n if (this.removed) {\n return this;\n }\n if (element.constructor == R.st.constructor) {\n element = element[0];\n }\n element.node.parentNode.insertBefore(this.node, element.node);\n R._insertbefore(this, element, this.paper);\n return this;\n };\n elproto.blur = function (size) {\n var s = this.node.runtimeStyle,\n f = s.filter;\n f = f.replace(blurregexp, E);\n if (+size !== 0) {\n this.attrs.blur = size;\n s.filter = f + S + ms + \".Blur(pixelradius=\" + (+size || 1.5) + \")\";\n s.margin = R.format(\"-{0}px 0 0 -{0}px\", round(+size || 1.5));\n } else {\n s.filter = f;\n s.margin = 0;\n delete this.attrs.blur;\n }\n return this;\n };\n\n R._engine.path = function (pathString, vml) {\n var el = createNode(\"shape\");\n el.style.cssText = cssDot;\n el.coordsize = zoom + S + zoom;\n el.coordorigin = vml.coordorigin;\n var p = new Element(el, vml),\n attr = {fill: \"none\", stroke: \"#000\"};\n pathString && (attr.path = pathString);\n p.type = \"path\";\n p.path = [];\n p.Path = E;\n setFillAndStroke(p, attr);\n vml.canvas.appendChild(el);\n var skew = createNode(\"skew\");\n skew.on = true;\n el.appendChild(skew);\n p.skew = skew;\n p.transform(E);\n return p;\n };\n R._engine.rect = function (vml, x, y, w, h, r) {\n var path = R._rectPath(x, y, w, h, r),\n res = vml.path(path),\n a = res.attrs;\n res.X = a.x = x;\n res.Y = a.y = y;\n res.W = a.width = w;\n res.H = a.height = h;\n a.r = r;\n a.path = path;\n res.type = \"rect\";\n return res;\n };\n R._engine.ellipse = function (vml, x, y, rx, ry) {\n var res = vml.path(),\n a = res.attrs;\n res.X = x - rx;\n res.Y = y - ry;\n res.W = rx * 2;\n res.H = ry * 2;\n res.type = \"ellipse\";\n setFillAndStroke(res, {\n cx: x,\n cy: y,\n rx: rx,\n ry: ry\n });\n return res;\n };\n R._engine.circle = function (vml, x, y, r) {\n var res = vml.path(),\n a = res.attrs;\n res.X = x - r;\n res.Y = y - r;\n res.W = res.H = r * 2;\n res.type = \"circle\";\n setFillAndStroke(res, {\n cx: x,\n cy: y,\n r: r\n });\n return res;\n };\n R._engine.image = function (vml, src, x, y, w, h) {\n var path = R._rectPath(x, y, w, h),\n res = vml.path(path).attr({stroke: \"none\"}),\n a = res.attrs,\n node = res.node,\n fill = node.getElementsByTagName(fillString)[0];\n a.src = src;\n res.X = a.x = x;\n res.Y = a.y = y;\n res.W = a.width = w;\n res.H = a.height = h;\n a.path = path;\n res.type = \"image\";\n fill.parentNode == node && node.removeChild(fill);\n fill.rotate = true;\n fill.src = src;\n fill.type = \"tile\";\n res._.fillpos = [x, y];\n res._.fillsize = [w, h];\n node.appendChild(fill);\n setCoords(res, 1, 1, 0, 0, 0);\n return res;\n };\n R._engine.text = function (vml, x, y, text) {\n var el = createNode(\"shape\"),\n path = createNode(\"path\"),\n o = createNode(\"textpath\");\n x = x || 0;\n y = y || 0;\n text = text || \"\";\n path.v = R.format(\"m{0},{1}l{2},{1}\", round(x * zoom), round(y * zoom), round(x * zoom) + 1);\n path.textpathok = true;\n o.string = Str(text);\n o.on = true;\n el.style.cssText = cssDot;\n el.coordsize = zoom + S + zoom;\n el.coordorigin = \"0 0\";\n var p = new Element(el, vml),\n attr = {\n fill: \"#000\",\n stroke: \"none\",\n font: R._availableAttrs.font,\n text: text\n };\n p.shape = el;\n p.path = path;\n p.textpath = o;\n p.type = \"text\";\n p.attrs.text = Str(text);\n p.attrs.x = x;\n p.attrs.y = y;\n p.attrs.w = 1;\n p.attrs.h = 1;\n setFillAndStroke(p, attr);\n el.appendChild(o);\n el.appendChild(path);\n vml.canvas.appendChild(el);\n var skew = createNode(\"skew\");\n skew.on = true;\n el.appendChild(skew);\n p.skew = skew;\n p.transform(E);\n return p;\n };\n R._engine.setSize = function (width, height) {\n var cs = this.canvas.style;\n this.width = width;\n this.height = height;\n width == +width && (width += \"px\");\n height == +height && (height += \"px\");\n cs.width = width;\n cs.height = height;\n cs.clip = \"rect(0 \" + width + \" \" + height + \" 0)\";\n if (this._viewBox) {\n R._engine.setViewBox.apply(this, this._viewBox);\n }\n return this;\n };\n R._engine.setViewBox = function (x, y, w, h, fit) {\n R.eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n var paperSize = this.getSize(),\n width = paperSize.width,\n height = paperSize.height,\n H, W;\n if (fit) {\n H = height / h;\n W = width / w;\n if (w * H < width) {\n x -= (width - w * H) / 2 / H;\n }\n if (h * W < height) {\n y -= (height - h * W) / 2 / W;\n }\n }\n this._viewBox = [x, y, w, h, !!fit];\n this._viewBoxShift = {\n dx: -x,\n dy: -y,\n scale: paperSize\n };\n this.forEach(function (el) {\n el.transform(\"...\");\n });\n return this;\n };\n var createNode;\n R._engine.initWin = function (win) {\n var doc = win.document;\n if (doc.styleSheets.length < 31) {\n doc.createStyleSheet().addRule(\".rvml\", \"behavior:url(#default#VML)\");\n } else {\n // no more room, add to the existing one\n // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx\n doc.styleSheets[0].addRule(\".rvml\", \"behavior:url(#default#VML)\");\n }\n try {\n !doc.namespaces.rvml && doc.namespaces.add(\"rvml\", \"urn:schemas-microsoft-com:vml\");\n createNode = function (tagName) {\n return doc.createElement('');\n };\n } catch (e) {\n createNode = function (tagName) {\n return doc.createElement('<' + tagName + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">');\n };\n }\n };\n R._engine.initWin(R._g.win);\n R._engine.create = function () {\n var con = R._getContainer.apply(0, arguments),\n container = con.container,\n height = con.height,\n s,\n width = con.width,\n x = con.x,\n y = con.y;\n if (!container) {\n throw new Error(\"VML container not found.\");\n }\n var res = new R._Paper,\n c = res.canvas = R._g.doc.createElement(\"div\"),\n cs = c.style;\n x = x || 0;\n y = y || 0;\n width = width || 512;\n height = height || 342;\n res.width = width;\n res.height = height;\n width == +width && (width += \"px\");\n height == +height && (height += \"px\");\n res.coordsize = zoom * 1e3 + S + zoom * 1e3;\n res.coordorigin = \"0 0\";\n res.span = R._g.doc.createElement(\"span\");\n res.span.style.cssText = \"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;\";\n c.appendChild(res.span);\n cs.cssText = R.format(\"top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden\", width, height);\n if (container == 1) {\n R._g.doc.body.appendChild(c);\n cs.left = x + \"px\";\n cs.top = y + \"px\";\n cs.position = \"absolute\";\n } else {\n if (container.firstChild) {\n container.insertBefore(c, container.firstChild);\n } else {\n container.appendChild(c);\n }\n }\n res.renderfix = function () {};\n return res;\n };\n R.prototype.clear = function () {\n R.eve(\"raphael.clear\", this);\n this.canvas.innerHTML = E;\n this.span = R._g.doc.createElement(\"span\");\n this.span.style.cssText = \"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;\";\n this.canvas.appendChild(this.span);\n this.bottom = this.top = null;\n };\n R.prototype.remove = function () {\n R.eve(\"raphael.remove\", this);\n this.canvas.parentNode.removeChild(this.canvas);\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n return true;\n };\n\n var setproto = R.st;\n for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n setproto[method] = (function (methodname) {\n return function () {\n var arg = arguments;\n return this.forEach(function (el) {\n el[methodname].apply(el, arg);\n });\n };\n })(method);\n }\n}));\n\n// ┌────────────────────────────────────────────────────────────────────┠\\\\\n// │ Raphaël @VERSION - JavaScript Vector Library │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com) │ \\\\\n// │ Copyright © 2008-2012 Sencha Labs (http://sencha.com) │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\\\\n// └────────────────────────────────────────────────────────────────────┘ \\\\\n\n(function (glob, factory) {\n if (typeof define === \"function\" && define.amd) {\n define(\"raphael\", [\"raphael.core\", \"raphael.svg\", \"raphael.vml\"], function(Raphael) {\n return (glob.Raphael = factory(Raphael));\n });\n } else if (typeof exports === \"object\") {\n var raphael = require(\"raphael.core\");\n\n require(\"raphael.svg\");\n require(\"raphael.vml\");\n\n module.exports = factory(raphael);\n } else {\n glob.Raphael = factory(glob.Raphael);\n }\n}(this, function (Raphael) {\n return Raphael.ninja();\n}));\n\n\n\n\n\n\n\n\n\n/**\n * FRaphael\n * \tAn extension for Raphael.js to make it easier to work with Filter Effects\n *\n * Copyright © 2013 Chris Scott \n * Delivered with and licensed under the MIT licence\n *\n */\n\n// Create the global FRaphael object\n(function(scope) {\n var\tversion = \"0.0.1\",\n license = \"MIT\";\n\n var\tns = \"http://www.w3.org/2000/svg\",\n idCounter = 0;\n\n var FR = {\n // Object prototype for a filter\n Filter: function(id) {\n if (id == undefined) {\n id = \"filter-\" + idCounter++;\n while(FR.filters[id] != undefined) {\n id = \"filter-\" + idCounter++;\n }\n }\n\n if (FR.filters[id] != undefined) {\n throw \"A filter with id \" + id + \" already exists\";\n }\n\n this.element = document.createElementNS(ns, \"filter\");\n this.element.setAttribute(\"id\", id);\n this.element.setAttribute(\"x\", \"-25%\");\n this.element.setAttribute(\"y\", \"-25%\");\n this.element.setAttribute(\"width\", \"150%\");\n this.element.setAttribute(\"height\", \"150%\");\n\n this.lastFEResult = null;\n\n FR.filters[id] = this;\n this.id = id;\n },\n\n // Object prototype for an effect\n FilterEffect: function(type, attributes) {\n this.element = document.createElementNS(ns, type);\n for (var key in attributes) {\n this.element.setAttribute(key, attributes[key]);\n }\n },\n\n // Return the filter applied to an element or a new filter if none are currently applied\n getFilter: function(element) {\n var filterId = element.data(\"filterId\");\n var filter = null;\n\n if (filterId == undefined) {\n filterId = \"element-filter-\" + element.id;\n filter = element.paper.createFilter(filterId);\n element.filter(filterId);\n } else {\n filter = FR.filters[filterId];\n }\n\n return filter;\n },\n\n // maintain a list of filters by id\n filters: {}\n };\n\n FR.Filter.prototype = {\n addEffect: function(type, attributes, children) {\n var effect = new FR.FilterEffect(type, attributes);\n\n if (children) {\n if (children instanceof Array) {\n for (var x in children) {\n if (!children.hasOwnProperty(x)) continue;\n\n effect.element.appendChild(children[x].element);\n }\n } else {\n effect.element.appendChild(children.element);\n }\n }\n\n this.element.appendChild(effect.element);\n\n return this;\n },\n\n chainEffect: function(type, attributes, children) {\n if (attributes == undefined) {\n attributes = {};\n }\n\n var inId;\n var outId;\n if (attributes.in == undefined) {\n inId = this.getLastResult();\n } else {\n inId = attributes.in;\n }\n if (attributes.result == undefined) {\n outId = idCounter++;\n } else {\n outId = attributes.result;\n }\n\n this.lastFEResult = outId;\n\n attributes.in = inId;\n attributes.result = outId;\n\n this.addEffect(type, attributes, children);\n\n return this;\n },\n\n getLastResult: function() {\n return (this.lastFEResult == undefined) ? \"SourceGraphic\" : this.lastFEResult;\n },\n\n merge: function(in1, in2, attributes) {\n var mergeNode1 = new FR.FilterEffect(\"feMergeNode\", {\n in: in1\n });\n var mergeNode2 = new FR.FilterEffect(\"feMergeNode\", {\n in: in2\n });\n\n this.chainEffect(\"feMerge\", attributes, [mergeNode1, mergeNode2]);\n\n return this;\n },\n\n compose: function(in1, in2, operator, attributes) {\n if (attributes == undefined) {\n attributes = {};\n }\n\n if (operator == undefined) {\n operator = \"over\";\n }\n\n attributes.in = in1;\n attributes.in2 = in2;\n attributes.operator = operator;\n\n this.chainEffect(\"feComposite\", attributes);\n\n return this;\n },\n\n arithmeticCompose: function(in1, in2, k1, k2, k3, k4) {\n if (k1 == undefined) {\n k1 = 0;\n }\n if (k2 == undefined) {\n k2 = 0;\n }\n if (k3 == undefined) {\n k3 = 0;\n }\n if (k4 == undefined) {\n k4 = 0;\n }\n\n this.compose(in1, in2, \"arithmetic\", {\n k1: k1,\n k2: k2,\n k3: k3,\n k4: k4\n });\n\n return this;\n },\n\n addBlur: function(stdDeviation, attributes) {\n if (!stdDeviation) {\n throw \"Standard deviation is required to perform a blur filter\";\n }\n\n if (attributes == undefined) {\n attributes = {};\n }\n attributes.stdDeviation = stdDeviation;\n\n this.chainEffect(\"feGaussianBlur\", attributes);\n\n return this;\n },\n\n addOffset: function(dx, dy, attributes) {\n if (dx == undefined | dy == undefined) {\n throw \"dx and dy values are required to perform an offset FE\";\n }\n\n if (attributes == undefined) {\n attributes = {};\n }\n attributes.dx = dx;\n attributes.dy = dy;\n\n this.chainEffect(\"feOffset\", attributes);\n\n return this;\n },\n\n addLighting: function(x, y, z, color, type, attributes) {\n if (x == undefined | y == undefined | z == undefined) {\n throw \"Three co-ordinates are required to create a light source\";\n }\n\n var previousResult = this.getLastResult();\n\n var id = idCounter++;\n\n if (attributes == undefined) {\n attributes = {};\n }\n\n attributes.result = id;\n if (color != undefined) {\n attributes[\"lighting-color\"] = color;\n }\n\n if (type == undefined || type == \"diffuse\") {\n type = \"feDiffuseLighting\";\n } else if (type == \"specular\") {\n type = \"feSpecularLighting\";\n }\n\n var lightSource = new FR.FilterEffect(\"fePointLight\", {\n x: x,\n y: y,\n z: z\n });\n\n this.chainEffect(type, attributes, lightSource).arithmeticCompose(previousResult, id, 3, 0.2, 0, 0);\n\n return this;\n },\n\n addShiftToColor: function(color, moveBy, attributes) {\n if (color == undefined) {\n throw \"A colour string is a required argument to create a colorMatrix\";\n }\n if (moveBy == undefined) {\n moveBy = 0.5;\n }\n\n var remainingColor = 1 - moveBy, x = remainingColor;\n\n if (attributes == undefined) {\n attributes = {};\n }\n\n var colorObject = Raphael.color(color);\n var\tr = colorObject.r * moveBy / 255,\n g = colorObject.g * moveBy / 255,\n b = colorObject.b * moveBy / 255;\n\n /**\n * r'\tx 0 0 0 r\t\tr\n * g'\t0 x 0 0 g\t\tg\n * b' =\t0 0 x 0 b\t.\tb\n * a'\t0 0 0 1 0\t\to\n * 1\t\t\t\t\t1\n */\n attributes.values = x + \" 0 0 0 \" + r + \" 0 \" + x + \" 0 0 \" + g + \" 0 0 \" + x + \" 0 \" + b + \" 0 0 0 1 0 \";\n\n this.chainEffect(\"feColorMatrix\", attributes);\n\n return this;\n },\n\n addRecolor: function(color, opacity, attributes) {\n if (color == undefined) {\n throw \"A colour string is a required argument to create a colorMatrix\";\n }\n if (opacity == undefined) {\n opacity = 1;\n }\n\n if (attributes == undefined) {\n attributes = {};\n }\n\n var colorObject = Raphael.color(color);\n var\tr = colorObject.r / 255,\n g = colorObject.g / 255,\n b = colorObject.b / 255;\n\n /**\n * r'\t0 0 0 0 r\t\tr\n * g'\t0 0 0 0 g\t\tg\n * b' =\t0 0 0 0 b\t.\tb\n * a'\t0 0 0 a 0\t\ta\n * 1\t\t\t\t\t1\n */\n attributes.values = \"0 0 0 0 \" + r + \" 0 0 0 0 \" + g + \" 0 0 0 0 \" + b + \" 0 0 0 \" + opacity + \" 0 \";\n\n this.chainEffect(\"feColorMatrix\", attributes);\n\n return this;\n },\n\n addDesaturate: function(saturation, attributes) {\n if (saturation == undefined) {\n saturnation = 0;\n }\n\n if (attributes == undefined) {\n attributes = {};\n }\n\n attributes.values = saturation;\n attributes.type = \"saturate\";\n\n this.chainEffect(\"feColorMatrix\", attributes);\n\n return this;\n },\n\n addConvolveMatrix: function(matrix, attributes) {\n if (matrix == undefined) {\n throw \"A matrix (usually 9 numbers) must be provided to apply a convolve matrix transform\";\n }\n\n if (attributes == undefined) {\n attributes = {};\n }\n\n attributes.kernelMatrix = matrix;\n\n this.chainEffect(\"feConvolveMatrix\", attributes);\n\n return this;\n },\n\n createShadow: function(dx, dy, blur, opacity, color) {\n if (dx == undefined) {\n throw \"dx is required for the shadow effect\";\n }\n if (dy == undefined) {\n throw \"dy is required for the shadow effect\";\n }\n if (blur == undefined) {\n throw \"blur (stdDeviation) is required for the shadow effect\";\n }\n\n if (opacity == undefined) {\n opacity = 0.6;\n }\n\n var previousResult = this.getLastResult();\n\n if (color == undefined) {\n color = \"#000000\";\n }\n\n this.addOffset(dx, dy, {\n in: \"SourceAlpha\"\n });\n\n this.addRecolor(color, opacity);\n\n this.addBlur(blur);\n\n this.merge(this.getLastResult(), previousResult);\n\n return this;\n },\n\n createEmboss: function(height, x, y, z) {\n if (height == undefined) {\n height = 2;\n }\n if (x == undefined) {\n x = -1000;\n }\n if (y == undefined) {\n y = -5000;\n }\n if (z == undefined) {\n z = 300;\n }\n\n // Create the highlight\n\n this.addOffset(height * x / (x + y), height * y / (x + y), {\n in: \"SourceAlpha\"\n });\n\n this.addBlur(height * 0.5);\n\n var whiteLightSource = new FR.FilterEffect(\"fePointLight\", {\n x: x,\n y: y,\n z: z\n });\n\n this.chainEffect(\"feSpecularLighting\", {\n surfaceScale: height,\n specularConstant: 0.8,\n specularExponent: 15\n }, whiteLightSource);\n\n this.compose(this.getLastResult(), \"SourceAlpha\", \"in\");\n var whiteLight = this.getLastResult();\n\n // Create the lowlight\n\n this.addOffset(height * -1 * x / (x + y), height * -1 * y / (x + y), {\n in: \"SourceAlpha\"\n });\n\n this.addBlur(height * 0.5);\n\n var darkLightSource = new FR.FilterEffect(\"fePointLight\", {\n x: -1 * x,\n y: -1 * y,\n z: z\n });\n\n this.chainEffect(\"feSpecularLighting\", {\n surfaceScale: height,\n specularConstant: 1.8,\n specularExponent: 6\n }, darkLightSource);\n\n this.compose(this.getLastResult(), \"SourceAlpha\", \"in\");\n this.chainEffect(\"feColorMatrix\", {\n values: \"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\"\n });\n var darkLight = this.getLastResult();\n\n this.arithmeticCompose(whiteLight, darkLight, 0, 0.8, 0.5, 0);\n\n this.merge(\"SourceGraphic\", this.getLastResult());\n\n return this;\n }\n };\n\n scope.FRaphael = FR;\n})(this);\n\n/**\n * add a filter to the paper by id\n */\nRaphael.fn.createFilter = function(id) {\n var paper = this;\n var filter = new FRaphael.Filter(id);\n paper.defs.appendChild(filter.element);\n\n return filter;\n};\n\n/**\n * Apply a filter to an element by id\n */\nRaphael.el.filter = function(filter) {\n var id = (filter instanceof FRaphael.Filter) ? filter.id : filter;\n\n this.node.setAttribute(\"filter\", \"url(#\" + id + \")\");\n this.data(\"filterId\", id);\n\n return this;\n};\n\n/**\n * Get the current filter for an element or a new one if not\n */\nRaphael.el.getFilter = function() {\n return FRaphael.getFilter(this);\n};\n\n/**\n * A shorthand method for applying blur\n */\nRaphael.el.blur = function(stdDeviation) {\n if (stdDeviation == undefined) {\n stdDeviation = 3;\n }\n\n this.getFilter().addBlur(stdDeviation);\n\n return this;\n};\n\n/**\n * A shorthand method for applying a drop shadow\n */\nRaphael.el.shadow = function(dx, dy, blur, opacity, color) {\n if (dx == undefined) {\n dx = 3;\n }\n if (dy == undefined) {\n dy = 3;\n }\n if (blur == undefined) {\n blur = 3;\n }\n\n this.getFilter().createShadow(dx, dy, blur, opacity, color);\n\n return this;\n};\n\n/**\n * A shorthand method for applying lighting\n */\nRaphael.el.light = function(x, y, z, color, type) {\n if (x == undefined) {\n x = this.paper.width;\n }\n if (y == undefined) {\n y = 0;\n }\n if (z == undefined) {\n z = 20;\n }\n\n this.getFilter().addLighting(x, y, z, color, type);\n\n return this;\n};\n\n/**\n * A shorthand method for applying a colour shift\n */\nRaphael.el.colorShift = function(color, shift) {\n if (color == undefined) {\n color = \"black\";\n }\n if (shift == undefined) {\n shift = 0.5;\n }\n\n this.getFilter().addShiftToColor(color, shift);\n\n return this;\n};\n\n/**\n * A shorthand method for embossing\n */\nRaphael.el.emboss = function(height) {\n this.getFilter().createEmboss(height);\n\n return this;\n};\n\n/**\n * A shorthand method for desaturating\n */\nRaphael.el.desaturate = function(saturation) {\n this.getFilter().addDesaturate(saturation);\n\n return this;\n};\n\n/**\n * A shorthand method for complete desaturation\n */\nRaphael.el.greyScale = function() {\n this.getFilter().addDesaturate(0);\n\n return this;\n};\n"
+
+/***/ }),
+
+/***/ "./node_modules/rgbcolor/index.js":
+/*!****************************************!*\
+ !*** ./node_modules/rgbcolor/index.js ***!
+ \****************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+/*
+ Based on rgbcolor.js by Stoyan Stefanov
+ http://www.phpied.com/rgb-color-parser-in-javascript/
+*/
+
+module.exports = function(color_string) {
+ this.ok = false;
+ this.alpha = 1.0;
+
+ // strip any leading #
+ if (color_string.charAt(0) == '#') { // remove # if any
+ color_string = color_string.substr(1,6);
+ }
+
+ color_string = color_string.replace(/ /g,'');
+ color_string = color_string.toLowerCase();
+
+ // before getting into regexps, try simple matches
+ // and overwrite the input
+ var simple_colors = {
+ aliceblue: 'f0f8ff',
+ antiquewhite: 'faebd7',
+ aqua: '00ffff',
+ aquamarine: '7fffd4',
+ azure: 'f0ffff',
+ beige: 'f5f5dc',
+ bisque: 'ffe4c4',
+ black: '000000',
+ blanchedalmond: 'ffebcd',
+ blue: '0000ff',
+ blueviolet: '8a2be2',
+ brown: 'a52a2a',
+ burlywood: 'deb887',
+ cadetblue: '5f9ea0',
+ chartreuse: '7fff00',
+ chocolate: 'd2691e',
+ coral: 'ff7f50',
+ cornflowerblue: '6495ed',
+ cornsilk: 'fff8dc',
+ crimson: 'dc143c',
+ cyan: '00ffff',
+ darkblue: '00008b',
+ darkcyan: '008b8b',
+ darkgoldenrod: 'b8860b',
+ darkgray: 'a9a9a9',
+ darkgreen: '006400',
+ darkkhaki: 'bdb76b',
+ darkmagenta: '8b008b',
+ darkolivegreen: '556b2f',
+ darkorange: 'ff8c00',
+ darkorchid: '9932cc',
+ darkred: '8b0000',
+ darksalmon: 'e9967a',
+ darkseagreen: '8fbc8f',
+ darkslateblue: '483d8b',
+ darkslategray: '2f4f4f',
+ darkturquoise: '00ced1',
+ darkviolet: '9400d3',
+ deeppink: 'ff1493',
+ deepskyblue: '00bfff',
+ dimgray: '696969',
+ dodgerblue: '1e90ff',
+ feldspar: 'd19275',
+ firebrick: 'b22222',
+ floralwhite: 'fffaf0',
+ forestgreen: '228b22',
+ fuchsia: 'ff00ff',
+ gainsboro: 'dcdcdc',
+ ghostwhite: 'f8f8ff',
+ gold: 'ffd700',
+ goldenrod: 'daa520',
+ gray: '808080',
+ green: '008000',
+ greenyellow: 'adff2f',
+ 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',
+ lightgrey: 'd3d3d3',
+ lightgreen: '90ee90',
+ lightpink: 'ffb6c1',
+ lightsalmon: 'ffa07a',
+ lightseagreen: '20b2aa',
+ lightskyblue: '87cefa',
+ lightslateblue: '8470ff',
+ lightslategray: '778899',
+ lightsteelblue: 'b0c4de',
+ lightyellow: 'ffffe0',
+ lime: '00ff00',
+ limegreen: '32cd32',
+ linen: 'faf0e6',
+ magenta: 'ff00ff',
+ maroon: '800000',
+ mediumaquamarine: '66cdaa',
+ mediumblue: '0000cd',
+ mediumorchid: 'ba55d3',
+ mediumpurple: '9370d8',
+ 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: 'd87093',
+ papayawhip: 'ffefd5',
+ peachpuff: 'ffdab9',
+ peru: 'cd853f',
+ pink: 'ffc0cb',
+ plum: 'dda0dd',
+ powderblue: 'b0e0e6',
+ purple: '800080',
+ red: 'ff0000',
+ rosybrown: 'bc8f8f',
+ royalblue: '4169e1',
+ saddlebrown: '8b4513',
+ salmon: 'fa8072',
+ sandybrown: 'f4a460',
+ seagreen: '2e8b57',
+ seashell: 'fff5ee',
+ sienna: 'a0522d',
+ silver: 'c0c0c0',
+ skyblue: '87ceeb',
+ slateblue: '6a5acd',
+ slategray: '708090',
+ snow: 'fffafa',
+ springgreen: '00ff7f',
+ steelblue: '4682b4',
+ tan: 'd2b48c',
+ teal: '008080',
+ thistle: 'd8bfd8',
+ tomato: 'ff6347',
+ turquoise: '40e0d0',
+ violet: 'ee82ee',
+ violetred: 'd02090',
+ wheat: 'f5deb3',
+ white: 'ffffff',
+ whitesmoke: 'f5f5f5',
+ yellow: 'ffff00',
+ yellowgreen: '9acd32'
+ };
+ color_string = simple_colors[color_string] || color_string;
+ // emd of simple type-in colors
+
+ // array of color definition objects
+ var color_defs = [
+ {
+ re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*((?:\d?\.)?\d)\)$/,
+ example: ['rgba(123, 234, 45, 0.8)', 'rgba(255,234,245,1.0)'],
+ process: function (bits){
+ return [
+ parseInt(bits[1]),
+ parseInt(bits[2]),
+ parseInt(bits[3]),
+ parseFloat(bits[4])
+ ];
+ }
+ },
+ {
+ re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
+ example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
+ process: function (bits){
+ return [
+ parseInt(bits[1]),
+ parseInt(bits[2]),
+ parseInt(bits[3])
+ ];
+ }
+ },
+ {
+ re: /^(\w{2})(\w{2})(\w{2})$/,
+ example: ['#00ff00', '336699'],
+ process: function (bits){
+ return [
+ parseInt(bits[1], 16),
+ parseInt(bits[2], 16),
+ parseInt(bits[3], 16)
+ ];
+ }
+ },
+ {
+ re: /^(\w{1})(\w{1})(\w{1})$/,
+ example: ['#fb0', 'f0f'],
+ process: function (bits){
+ return [
+ parseInt(bits[1] + bits[1], 16),
+ parseInt(bits[2] + bits[2], 16),
+ parseInt(bits[3] + bits[3], 16)
+ ];
+ }
+ }
+ ];
+
+ // search through the definitions to find a match
+ for (var i = 0; i < color_defs.length; i++) {
+ var re = color_defs[i].re;
+ var processor = color_defs[i].process;
+ var bits = re.exec(color_string);
+ if (bits) {
+ var channels = processor(bits);
+ this.r = channels[0];
+ this.g = channels[1];
+ this.b = channels[2];
+ if (channels.length > 3) {
+ this.alpha = channels[3];
+ }
+ this.ok = true;
+ }
+
+ }
+
+ // validate/cleanup values
+ this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
+ this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
+ this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
+ this.alpha = (this.alpha < 0) ? 0 : ((this.alpha > 1.0 || isNaN(this.alpha)) ? 1.0 : this.alpha);
+
+ // some getters
+ this.toRGB = function () {
+ return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
+ }
+ this.toRGBA = function () {
+ return 'rgba(' + this.r + ', ' + this.g + ', ' + this.b + ', ' + this.alpha + ')';
+ }
+ this.toHex = function () {
+ var r = this.r.toString(16);
+ var g = this.g.toString(16);
+ var b = this.b.toString(16);
+ if (r.length == 1) r = '0' + r;
+ if (g.length == 1) g = '0' + g;
+ if (b.length == 1) b = '0' + b;
+ return '#' + r + g + b;
+ }
+
+ // help
+ this.getHelpXML = function () {
+
+ var examples = new Array();
+ // add regexps
+ for (var i = 0; i < color_defs.length; i++) {
+ var example = color_defs[i].example;
+ for (var j = 0; j < example.length; j++) {
+ examples[examples.length] = example[j];
+ }
+ }
+ // add type-in colors
+ for (var sc in simple_colors) {
+ examples[examples.length] = sc;
+ }
+
+ var xml = document.createElement('ul');
+ xml.setAttribute('id', 'rgbcolor-examples');
+ for (var i = 0; i < examples.length; i++) {
+ try {
+ var list_item = document.createElement('li');
+ var list_color = new RGBColor(examples[i]);
+ var example_div = document.createElement('div');
+ example_div.style.cssText =
+ 'margin: 3px; '
+ + 'border: 1px solid black; '
+ + 'background:' + list_color.toHex() + '; '
+ + 'color:' + list_color.toHex()
+ ;
+ example_div.appendChild(document.createTextNode('test'));
+ var list_item_value = document.createTextNode(
+ ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
+ );
+ list_item.appendChild(example_div);
+ list_item.appendChild(list_item_value);
+ xml.appendChild(list_item);
+
+ } catch(e){}
+ }
+ return xml;
+
+ }
+
+}
+
+
+/***/ }),
+
+/***/ "./node_modules/script-loader/addScript.js":
+/*!*************************************************!*\
+ !*** ./node_modules/script-loader/addScript.js ***!
+ \*************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+module.exports = function(src) {
+ function log(error) {
+ (typeof console !== "undefined")
+ && (console.error || console.log)("[Script Loader]", error);
+ }
+
+ // Check for IE =< 8
+ function isIE() {
+ return typeof attachEvent !== "undefined" && typeof addEventListener === "undefined";
+ }
+
+ try {
+ if (typeof execScript !== "undefined" && isIE()) {
+ execScript(src);
+ } else if (typeof eval !== "undefined") {
+ eval.call(null, src);
+ } else {
+ log("EvalError: No eval function available");
+ }
+ } catch (error) {
+ log(error);
+ }
+}
+
+
+/***/ }),
+
+/***/ "./node_modules/shifty/dist/shifty.js":
+/*!********************************************!*\
+ !*** ./node_modules/shifty/dist/shifty.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+/*! 2.3.1 */
+!function(t,e){ true?module.exports=e():undefined}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/assets/",e(e.s=6)}([function(t,e,n){"use strict";(function(t){function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=new j,n=e.tween(t);return n.tweenable=e,n}Object.defineProperty(e,"__esModule",{value:!0}),e.Tweenable=e.composeEasingObject=e.tweenProps=e.clone=e.each=void 0;var u=function(){function t(t,e){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"linear",n={},r=void 0===e?"undefined":a(e);return"string"===r||"function"===r?y(t,function(t){return n[t]=e}):y(t,function(t){return n[t]=n[t]||e[t]||"linear"}),n},j=e.Tweenable=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;i(this,t),this._currentState=e,this._configured=!1,this._scheduleFunction=_,void 0!==n&&this.setConfig(n)}return u(t,[{key:"_applyFilter",value:function(e){var n=this,r=t.filters,i=this._filterArgs;y(r,function(t){var o=r[t][e];void 0!==o&&o.apply(n,i)})}},{key:"_timeoutHandler",value:function(e){var n=this,r=arguments,i=this._currentState,o=this._delay,u=this._duration,a=this._step,c=this._targetState,s=this._timestamp,f=s+o+u,h=Math.min(e||t.now(),f),l=h>=f,p=u-(f-h);this.isPlaying()&&(l?(a(c,this._attachment,p),this.stop(!0)):(this._scheduleId=this._scheduleFunction.call(d,function(){return n._timeoutHandler.apply(n,r)},1e3/60),this._applyFilter("beforeTween"),h0&&void 0!==arguments[0]?arguments[0]:void 0,n=this._attachment,r=this._configured;return this._isTweening?this:(void 0===e&&r||this.setConfig(e),this._timestamp=t.now(),this._start(this.get(),n),this.resume())}},{key:"setConfig",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this._configured=!0,this._attachment=e.attachment,(0,h.default)(this,{_pausedAtTime:null,_scheduleId:null,_delay:e.delay||0,_start:e.start||v,_step:e.step||v,_duration:e.duration||500,_currentState:w(e.from||this.get())}),(0,h.default)(this,{_originalState:this.get(),_targetState:w(e.to||this.get())});var n=this._currentState;this._targetState=(0,h.default)({},n,this._targetState),this._easing=M(n,e.easing),this._filterArgs=[n,this._originalState,this._targetState,this._easing],this._applyFilter("tweenCreated");var r=e.promise||Promise;return this._promise=new r(function(e,n){t._resolve=e,t._reject=n}),this._promise.catch(v),this}},{key:"get",value:function(){return w(this._currentState)}},{key:"set",value:function(t){this._currentState=t}},{key:"pause",value:function(){return this._pausedAtTime=t.now(),this._isPaused=!0,this}},{key:"resume",value:function(){return this._isPaused&&(this._timestamp+=t.now()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0,this._timeoutHandler(),this._promise}},{key:"seek",value:function(e){e=Math.max(e,0);var n=t.now();return this._timestamp+e===0?this:(this._timestamp=n-e,this.isPlaying()||(this._isTweening=!0,this._isPaused=!1,this._timeoutHandler(n),this.pause()),this)}},{key:"stop",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],e=this._attachment,n=this._currentState,r=this._easing,i=this._originalState,o=this._targetState;return this._isTweening=!1,this._isPaused=!1,m(this._scheduleId),t?(this._applyFilter("beforeTween"),O(1,n,i,o,1,0,r),this._applyFilter("afterTween"),this._applyFilter("afterTweenEnd"),this._resolve(n,e)):this._reject(n,e),this}},{key:"isPlaying",value:function(){return this._isTweening&&!this._isPaused}},{key:"setScheduleFunction",value:function(t){this._scheduleFunction=t}},{key:"dispose",value:function(){var t=this;y(this,function(e){return delete t[e]})}}]),t}();(0,h.default)(j,{formulas:g,filters:{token:p},now:Date.now||function(t){return+new Date}})}).call(e,n(4))},function(t,e,n){"use strict";function r(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}var i=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,u=Object.prototype.propertyIsEnumerable;t.exports=function(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(e).map(function(t){return e[t]}).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(t){r[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(t){return!1}}()?Object.assign:function(t,e){for(var n,a,c=r(t),s=1;s=0?t:0-t},_=function(t,e){var n=void 0,r=void 0,i=void 0,o=void 0,u=void 0,a=void 0;for(i=t,a=0;a<8;a++){if(o=l(i)-t,m(o)r)return r;for(;no?n=i:r=i,i=.5*(r-n)+n}return i};return c=3*e,a=3*(r-e)-c,u=1-c-a,h=3*n,f=3*(i-n)-h,s=1-h-f,function(t,e){return p(_(t,e))}(t,function(t){return 1/(200*t)}(o))}Object.defineProperty(e,"__esModule",{value:!0}),e.unsetBezierFunction=e.setBezierFunction=void 0;var i=n(0),o=n(1),u=function(t){return t&&t.__esModule?t:{default:t}}(o),a=function(t,e,n,i){return function(o){return r(o,t,e,n,i,1)}};e.setBezierFunction=function(t,e,n,r,o){return i.Tweenable.formulas[t]=(0,u.default)(a(e,n,r,o),{displayName:t,x1:e,y1:n,x2:r,y2:o})},e.unsetBezierFunction=function(t){return delete i.Tweenable.formulas[t]}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.interpolate=void 0;var r=n(0),i=new r.Tweenable;i._filterArgs=[];e.interpolate=function(t,e,n,o){var u=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=(0,r.clone)(t),c=(0,r.composeEasingObject)(t,o);i.set({}),i._filterArgs=[a,t,e,c],i._applyFilter("tweenCreated"),i._applyFilter("beforeTween");var s=(0,r.tweenProps)(n,a,t,e,1,u,c);return i._applyFilter("afterTween"),s}},function(t,e,n){"use strict";var r,i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(t){"object"===("undefined"==typeof window?"undefined":i(window))&&(r=window)}t.exports=r},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.linear=function(t){return t},e.easeInQuad=function(t){return Math.pow(t,2)},e.easeOutQuad=function(t){return-(Math.pow(t-1,2)-1)},e.easeInOutQuad=function(t){return(t/=.5)<1?.5*Math.pow(t,2):-.5*((t-=2)*t-2)},e.easeInCubic=function(t){return Math.pow(t,3)},e.easeOutCubic=function(t){return Math.pow(t-1,3)+1},e.easeInOutCubic=function(t){return(t/=.5)<1?.5*Math.pow(t,3):.5*(Math.pow(t-2,3)+2)},e.easeInQuart=function(t){return Math.pow(t,4)},e.easeOutQuart=function(t){return-(Math.pow(t-1,4)-1)},e.easeInOutQuart=function(t){return(t/=.5)<1?.5*Math.pow(t,4):-.5*((t-=2)*Math.pow(t,3)-2)},e.easeInQuint=function(t){return Math.pow(t,5)},e.easeOutQuint=function(t){return Math.pow(t-1,5)+1},e.easeInOutQuint=function(t){return(t/=.5)<1?.5*Math.pow(t,5):.5*(Math.pow(t-2,5)+2)},e.easeInSine=function(t){return 1-Math.cos(t*(Math.PI/2))},e.easeOutSine=function(t){return Math.sin(t*(Math.PI/2))},e.easeInOutSine=function(t){return-.5*(Math.cos(Math.PI*t)-1)},e.easeInExpo=function(t){return 0===t?0:Math.pow(2,10*(t-1))},e.easeOutExpo=function(t){return 1===t?1:1-Math.pow(2,-10*t)},e.easeInOutExpo=function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},e.easeInCirc=function(t){return-(Math.sqrt(1-t*t)-1)},e.easeOutCirc=function(t){return Math.sqrt(1-Math.pow(t-1,2))},e.easeInOutCirc=function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},e.easeOutBounce=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},e.easeInBack=function(t){var e=1.70158;return t*t*((e+1)*t-e)},e.easeOutBack=function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},e.easeInOutBack=function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},e.elastic=function(t){return-1*Math.pow(4,-8*t)*Math.sin((6*t-1)*(2*Math.PI)/2)+1},e.swingFromTo=function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},e.swingFrom=function(t){var e=1.70158;return t*t*((e+1)*t-e)},e.swingTo=function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},e.bounce=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},e.bouncePast=function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?2-(7.5625*(t-=1.5/2.75)*t+.75):t<2.5/2.75?2-(7.5625*(t-=2.25/2.75)*t+.9375):2-(7.5625*(t-=2.625/2.75)*t+.984375)},e.easeFromTo=function(t){return(t/=.5)<1?.5*Math.pow(t,4):-.5*((t-=2)*Math.pow(t,3)-2)},e.easeFrom=function(t){return Math.pow(t,4)},e.easeTo=function(t){return Math.pow(t,.25)}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(0);Object.defineProperty(e,"Tweenable",{enumerable:!0,get:function(){return r.Tweenable}}),Object.defineProperty(e,"tween",{enumerable:!0,get:function(){return r.tween}});var i=n(3);Object.defineProperty(e,"interpolate",{enumerable:!0,get:function(){return i.interpolate}});var o=n(2);Object.defineProperty(e,"setBezierFunction",{enumerable:!0,get:function(){return o.setBezierFunction}}),Object.defineProperty(e,"unsetBezierFunction",{enumerable:!0,get:function(){return o.unsetBezierFunction}})},function(t,e,n){"use strict";function r(t){return parseInt(t,16)}function i(t,e,n){[t,e,n].forEach(_),this._tokenData=g(t)}function o(t,e,n,r){var i=this._tokenData;P(r,i),[t,e,n].forEach(function(t){return b(t,i)})}function u(t,e,n,r){var i=this._tokenData;[t,e,n].forEach(function(t){return F(t,i)}),S(r,i)}Object.defineProperty(e,"__esModule",{value:!0}),e.tweenCreated=i,e.beforeTween=o,e.afterTween=u;var a=n(0),c=function(){var t=/[0-9.\-]+/g.source,e=/,\s*/.source;return new RegExp("rgb\\("+t+e+t+e+t+"\\)","g")}(),s=/#([0-9]|[a-f]){3,6}/gi,f=function(t,e){return t.map(function(t,n){return"_"+e+"_"+n})},h=function(t){var e=t.match(/([^\-0-9\.]+)/g);return e?(1===e.length||t.charAt(0).match(/(\d|\-|\.)/))&&e.unshift(""):e=["",""],e.join("VAL")},l=function(t){return t=t.replace(/#/,""),3===t.length&&(t=t.split(""),t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]),[r(t.substr(0,2)),r(t.substr(2,2)),r(t.substr(4,2))]},p=function(t){return"rgb("+l(t).join(",")+")"},d=function(t,e,n){var r=e.match(t),i=e.replace(t,"VAL");return r&&r.forEach(function(t){return i=i.replace("VAL",n(t))}),i},m=function(t){return d(s,t,p)},_=function(t){(0,a.each)(t,function(e){var n=t[e];"string"==typeof n&&n.match(s)&&(t[e]=m(n))})},v=function(t){var e=t.match(/[0-9.\-]+/g).map(Math.floor);return""+t.match(/^.*\(/)[0]+e.join(",")+")"},y=function(t){return d(c,t,v)},w=function(t){return t.match(/[0-9.\-]+/g)},g=function(t){var e={};return(0,a.each)(t,function(n){var r=t[n];"string"==typeof r&&(e[n]={formatString:h(r),chunkNames:f(w(r),n)})}),e},b=function(t,e){(0,a.each)(e,function(n){w(t[n]).forEach(function(r,i){return t[e[n].chunkNames[i]]=+r}),delete t[n]})},O=function(t,e){var n={};return e.forEach(function(e){n[e]=t[e],delete t[e]}),n},M=function(t,e){return e.map(function(e){return t[e]})},j=function(t,e){return e.forEach(function(e){return t=t.replace("VAL",+e.toFixed(4))}),t},F=function(t,e){(0,a.each)(e,function(n){var r=e[n],i=r.chunkNames,o=r.formatString,u=j(o,M(O(t,i),i));t[n]=y(u)})},P=function(t,e){(0,a.each)(e,function(n){var r=e[n].chunkNames,i=t[n];"string"==typeof i?function(){var e=i.split(" "),n=e[e.length-1];r.forEach(function(r,i){return t[r]=e[i]||n})}():r.forEach(function(e){return t[e]=i}),delete t[n]})},S=function(t,e){(0,a.each)(e,function(n){var r=e[n].chunkNames,i=(r.length,t[r[0]]);t[n]="string"==typeof i?r.map(function(e){var n=t[e];return delete t[e],n}).join(" "):i})}}])});
+//# sourceMappingURL=shifty.js.map
+
+/***/ }),
+
+/***/ "./node_modules/stackblur/index.js":
+/*!*****************************************!*\
+ !*** ./node_modules/stackblur/index.js ***!
+ \*****************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+/*
+
+StackBlur - a fast almost Gaussian Blur For Canvas
+
+Version: 0.5
+Author: Mario Klingemann
+Contact: mario@quasimondo.com
+Website: http://www.quasimondo.com/StackBlurForCanvas
+Twitter: @quasimondo
+
+In case you find this class useful - especially in commercial projects -
+I am not totally unhappy for a small donation to my PayPal account
+mario@quasimondo.de
+
+Or support me on flattr:
+https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript
+
+Copyright (c) 2010 Mario Klingemann
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+var mul_table = [
+ 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
+ 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
+ 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
+ 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
+ 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
+ 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
+ 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
+ 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
+ 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
+ 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
+ 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
+ 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
+ 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
+ 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
+ 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
+ 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259];
+
+
+var shg_table = [
+ 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
+ 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 ];
+
+function blur( pixels, width, height, radius )
+{
+ if ( isNaN(radius) || radius < 1 ) return;
+ radius |= 0;
+
+ var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, a_sum,
+ r_out_sum, g_out_sum, b_out_sum, a_out_sum,
+ r_in_sum, g_in_sum, b_in_sum, a_in_sum,
+ pr, pg, pb, pa, rbs;
+
+ var div = radius + radius + 1;
+ var w4 = width << 2;
+ var widthMinus1 = width - 1;
+ var heightMinus1 = height - 1;
+ var radiusPlus1 = radius + 1;
+ var sumFactor = radiusPlus1 * ( radiusPlus1 + 1 ) / 2;
+
+ var stackStart = new BlurStack();
+ var stack = stackStart;
+ for ( i = 1; i < div; i++ )
+ {
+ stack = stack.next = new BlurStack();
+ if ( i == radiusPlus1 ) var stackEnd = stack;
+ }
+ stack.next = stackStart;
+ var stackIn = null;
+ var stackOut = null;
+
+ yw = yi = 0;
+
+ var mul_sum = mul_table[radius];
+ var shg_sum = shg_table[radius];
+
+ for ( y = 0; y < height; y++ )
+ {
+ r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0;
+
+ r_out_sum = radiusPlus1 * ( pr = pixels[yi] );
+ g_out_sum = radiusPlus1 * ( pg = pixels[yi+1] );
+ b_out_sum = radiusPlus1 * ( pb = pixels[yi+2] );
+ a_out_sum = radiusPlus1 * ( pa = pixels[yi+3] );
+
+ r_sum += sumFactor * pr;
+ g_sum += sumFactor * pg;
+ b_sum += sumFactor * pb;
+ a_sum += sumFactor * pa;
+
+ stack = stackStart;
+
+ for( i = 0; i < radiusPlus1; i++ )
+ {
+ stack.r = pr;
+ stack.g = pg;
+ stack.b = pb;
+ stack.a = pa;
+ stack = stack.next;
+ }
+
+ for( i = 1; i < radiusPlus1; i++ )
+ {
+ p = yi + (( widthMinus1 < i ? widthMinus1 : i ) << 2 );
+ r_sum += ( stack.r = ( pr = pixels[p])) * ( rbs = radiusPlus1 - i );
+ g_sum += ( stack.g = ( pg = pixels[p+1])) * rbs;
+ b_sum += ( stack.b = ( pb = pixels[p+2])) * rbs;
+ a_sum += ( stack.a = ( pa = pixels[p+3])) * rbs;
+
+ r_in_sum += pr;
+ g_in_sum += pg;
+ b_in_sum += pb;
+ a_in_sum += pa;
+
+ stack = stack.next;
+ }
+
+
+ stackIn = stackStart;
+ stackOut = stackEnd;
+ for ( x = 0; x < width; x++ )
+ {
+ pixels[yi+3] = pa = (a_sum * mul_sum) >> shg_sum;
+ if ( pa != 0 )
+ {
+ pa = 255 / pa;
+ pixels[yi] = ((r_sum * mul_sum) >> shg_sum) * pa;
+ pixels[yi+1] = ((g_sum * mul_sum) >> shg_sum) * pa;
+ pixels[yi+2] = ((b_sum * mul_sum) >> shg_sum) * pa;
+ } else {
+ pixels[yi] = pixels[yi+1] = pixels[yi+2] = 0;
+ }
+
+ r_sum -= r_out_sum;
+ g_sum -= g_out_sum;
+ b_sum -= b_out_sum;
+ a_sum -= a_out_sum;
+
+ r_out_sum -= stackIn.r;
+ g_out_sum -= stackIn.g;
+ b_out_sum -= stackIn.b;
+ a_out_sum -= stackIn.a;
+
+ p = ( yw + ( ( p = x + radius + 1 ) < widthMinus1 ? p : widthMinus1 ) ) << 2;
+
+ r_in_sum += ( stackIn.r = pixels[p]);
+ g_in_sum += ( stackIn.g = pixels[p+1]);
+ b_in_sum += ( stackIn.b = pixels[p+2]);
+ a_in_sum += ( stackIn.a = pixels[p+3]);
+
+ r_sum += r_in_sum;
+ g_sum += g_in_sum;
+ b_sum += b_in_sum;
+ a_sum += a_in_sum;
+
+ stackIn = stackIn.next;
+
+ r_out_sum += ( pr = stackOut.r );
+ g_out_sum += ( pg = stackOut.g );
+ b_out_sum += ( pb = stackOut.b );
+ a_out_sum += ( pa = stackOut.a );
+
+ r_in_sum -= pr;
+ g_in_sum -= pg;
+ b_in_sum -= pb;
+ a_in_sum -= pa;
+
+ stackOut = stackOut.next;
+
+ yi += 4;
+ }
+ yw += width;
+ }
+
+
+ for ( x = 0; x < width; x++ )
+ {
+ g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0;
+
+ yi = x << 2;
+ r_out_sum = radiusPlus1 * ( pr = pixels[yi]);
+ g_out_sum = radiusPlus1 * ( pg = pixels[yi+1]);
+ b_out_sum = radiusPlus1 * ( pb = pixels[yi+2]);
+ a_out_sum = radiusPlus1 * ( pa = pixels[yi+3]);
+
+ r_sum += sumFactor * pr;
+ g_sum += sumFactor * pg;
+ b_sum += sumFactor * pb;
+ a_sum += sumFactor * pa;
+
+ stack = stackStart;
+
+ for( i = 0; i < radiusPlus1; i++ )
+ {
+ stack.r = pr;
+ stack.g = pg;
+ stack.b = pb;
+ stack.a = pa;
+ stack = stack.next;
+ }
+
+ yp = width;
+
+ for( i = 1; i <= radius; i++ )
+ {
+ yi = ( yp + x ) << 2;
+
+ r_sum += ( stack.r = ( pr = pixels[yi])) * ( rbs = radiusPlus1 - i );
+ g_sum += ( stack.g = ( pg = pixels[yi+1])) * rbs;
+ b_sum += ( stack.b = ( pb = pixels[yi+2])) * rbs;
+ a_sum += ( stack.a = ( pa = pixels[yi+3])) * rbs;
+
+ r_in_sum += pr;
+ g_in_sum += pg;
+ b_in_sum += pb;
+ a_in_sum += pa;
+
+ stack = stack.next;
+
+ if( i < heightMinus1 )
+ {
+ yp += width;
+ }
+ }
+
+ yi = x;
+ stackIn = stackStart;
+ stackOut = stackEnd;
+ for ( y = 0; y < height; y++ )
+ {
+ p = yi << 2;
+ pixels[p+3] = pa = (a_sum * mul_sum) >> shg_sum;
+ if ( pa > 0 )
+ {
+ pa = 255 / pa;
+ pixels[p] = ((r_sum * mul_sum) >> shg_sum ) * pa;
+ pixels[p+1] = ((g_sum * mul_sum) >> shg_sum ) * pa;
+ pixels[p+2] = ((b_sum * mul_sum) >> shg_sum ) * pa;
+ } else {
+ pixels[p] = pixels[p+1] = pixels[p+2] = 0;
+ }
+
+ r_sum -= r_out_sum;
+ g_sum -= g_out_sum;
+ b_sum -= b_out_sum;
+ a_sum -= a_out_sum;
+
+ r_out_sum -= stackIn.r;
+ g_out_sum -= stackIn.g;
+ b_out_sum -= stackIn.b;
+ a_out_sum -= stackIn.a;
+
+ p = ( x + (( ( p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1 ) * width )) << 2;
+
+ r_sum += ( r_in_sum += ( stackIn.r = pixels[p]));
+ g_sum += ( g_in_sum += ( stackIn.g = pixels[p+1]));
+ b_sum += ( b_in_sum += ( stackIn.b = pixels[p+2]));
+ a_sum += ( a_in_sum += ( stackIn.a = pixels[p+3]));
+
+ stackIn = stackIn.next;
+
+ r_out_sum += ( pr = stackOut.r );
+ g_out_sum += ( pg = stackOut.g );
+ b_out_sum += ( pb = stackOut.b );
+ a_out_sum += ( pa = stackOut.a );
+
+ r_in_sum -= pr;
+ g_in_sum -= pg;
+ b_in_sum -= pb;
+ a_in_sum -= pa;
+
+ stackOut = stackOut.next;
+
+ yi += width;
+ }
+ }
+}
+
+function BlurStack()
+{
+ this.r = 0;
+ this.g = 0;
+ this.b = 0;
+ this.a = 0;
+ this.next = null;
+}
+
+module.exports = blur;
+
+/***/ }),
+
+/***/ "./node_modules/style-loader/lib/addStyles.js":
+/*!****************************************************!*\
+ !*** ./node_modules/style-loader/lib/addStyles.js ***!
+ \****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+var stylesInDom = {};
+
+var memoize = function (fn) {
+ var memo;
+
+ return function () {
+ if (typeof memo === "undefined") memo = fn.apply(this, arguments);
+ return memo;
+ };
+};
+
+var isOldIE = memoize(function () {
+ // Test for IE <= 9 as proposed by Browserhacks
+ // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
+ // Tests for existence of standard globals is to allow style-loader
+ // to operate correctly into non-standard environments
+ // @see https://github.com/webpack-contrib/style-loader/issues/177
+ return window && document && document.all && !window.atob;
+});
+
+var getTarget = function (target) {
+ return document.querySelector(target);
+};
+
+var getElement = (function (fn) {
+ var memo = {};
+
+ return function(target) {
+ // If passing function in options, then use it for resolve "head" element.
+ // Useful for Shadow Root style i.e
+ // {
+ // insertInto: function () { return document.querySelector("#foo").shadowRoot }
+ // }
+ if (typeof target === 'function') {
+ return target();
+ }
+ if (typeof memo[target] === "undefined") {
+ var styleTarget = getTarget.call(this, target);
+ // Special case to return head of iframe instead of iframe itself
+ if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
+ try {
+ // This will throw an exception if access to iframe is blocked
+ // due to cross-origin restrictions
+ styleTarget = styleTarget.contentDocument.head;
+ } catch(e) {
+ styleTarget = null;
+ }
+ }
+ memo[target] = styleTarget;
+ }
+ return memo[target]
+ };
+})();
+
+var singleton = null;
+var singletonCounter = 0;
+var stylesInsertedAtTop = [];
+
+var fixUrls = __webpack_require__(/*! ./urls */ "./node_modules/style-loader/lib/urls.js");
+
+module.exports = function(list, options) {
+ if (typeof DEBUG !== "undefined" && DEBUG) {
+ if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
+ }
+
+ options = options || {};
+
+ options.attrs = typeof options.attrs === "object" ? options.attrs : {};
+
+ // Force single-tag solution on IE6-9, which has a hard limit on the # of