aboutsummaryrefslogtreecommitdiff
path: root/files/de/web/css/tools
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:41:15 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:41:15 -0500
commit4b1a9203c547c019fc5398082ae19a3f3d4c3efe (patch)
treed4a40e13ceeb9f85479605110a76e7a4d5f3b56b /files/de/web/css/tools
parent33058f2b292b3a581333bdfb21b8f671898c5060 (diff)
downloadtranslated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.gz
translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.bz2
translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.zip
initial commit
Diffstat (limited to 'files/de/web/css/tools')
-rw-r--r--files/de/web/css/tools/cubic_bezier_generator/index.html321
-rw-r--r--files/de/web/css/tools/index.html25
-rw-r--r--files/de/web/css/tools/linear-gradient_generator/index.html3328
3 files changed, 3674 insertions, 0 deletions
diff --git a/files/de/web/css/tools/cubic_bezier_generator/index.html b/files/de/web/css/tools/cubic_bezier_generator/index.html
new file mode 100644
index 0000000000..a385d685be
--- /dev/null
+++ b/files/de/web/css/tools/cubic_bezier_generator/index.html
@@ -0,0 +1,321 @@
+---
+title: Cubic Bezier Generator
+slug: Web/CSS/Tools/Cubic_Bezier_Generator
+tags:
+ - CSS
+ - Werkzeuge
+translation_of: Web/CSS/Tools/Cubic_Bezier_Generator
+---
+<div id="Tool">
+<div style="display: none;">
+<pre class="brush:html">&lt;html&gt;
+ &lt;canvas id="bezier" width="336" height="336"&gt;
+ &lt;/canvas&gt;
+ &lt;form&gt;
+ &lt;label for="x1"&gt;x1 = &lt;/label&gt;&lt;input onchange="updateCanvas();" type="text" maxlength=6 id="x1" value="0.79" class='field'&gt;
+ &lt;label for="y1"&gt;y1 = &lt;/label&gt;&lt;input onchange="updateCanvas();return true;"  type="text" maxlength=6 id="y1" value="0.33" class='field'&gt;
+ &lt;label for="x2"&gt;x2 = &lt;/label&gt;&lt;input onchange="updateCanvas();return true;"  type="text" maxlength=6 id="x2" value="0.14" class='field'&gt;
+ &lt;label for="y2"&gt;y2 = &lt;/label&gt;&lt;input onchange="updateCanvas();return true;"  type="text" maxlength=6 id="y2" value="0.53" class='field'&gt;
+ &lt;br&gt;
+ &lt;output id="output"&gt;Log&lt;/output&gt;
+ &lt;/form&gt;
+&lt;/html&gt;
+ </pre>
+
+<pre class="brush:css">.field {
+ width: 40px;
+}
+ </pre>
+
+<pre class="brush:js">function updateCanvas() {
+
+ var x1 = document.getElementById('x1').value;
+ var y1 = document.getElementById('y1').value;
+ var x2 = document.getElementById('x2').value;
+ var y2 = document.getElementById('y2').value;
+
+ drawBezierCurve(x1, y1, x2, y2);
+}
+
+const radius = 4;
+// Place needed to draw the rulers
+const rulers = 30.5;
+const margin = 10.5;
+const basic_scale_size = 5; // Size of 0.1 tick on the rulers
+var scaling; //LIMITATION: scaling is computed once: if canvas.height/canvas.width change it won't be recalculated
+var dragSM = 0; // Drag state machine: 0 = nodrag, others = object being dragged
+
+function initCanvas() {
+ // get the canvas element using the DOM
+ var canvas = document.getElementById('bezier');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext) {
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+ scaling = Math.min(canvas.height - rulers - margin, canvas.width - rulers - margin);
+
+ canvas.onmousedown = mouseDown;
+ canvas.onmouseup = mouseUp;
+ } else {
+ alert('You need Safari or Firefox 1.5+ to see this demo.');
+ }
+}
+
+function cX(x) {
+ return x * scaling + rulers;
+}
+
+function reverseX(x) {
+ return (x - rulers) / scaling;
+}
+
+function lX(x) {
+ //Used when drawing vertical lines to prevent subpixel blur
+ var result = cX(x);
+ return Math.round(result) == result ? result + 0.5 : result;
+}
+
+function cY(y) {
+
+ return (1 - y) * scaling + margin;
+}
+
+function reverseY(y) {
+ return (margin - y) / scaling + 1;
+}
+
+function lY(y) {
+ // Used when drawing horizontal lines to prevent subpixel blur
+ var result = cY(y);
+ return Math.round(result) == result ? result + 0.5 : result;
+}
+
+function drawBezierCurve(x1, y1, x2, y2) {
+
+ // get the canvas element using the DOM
+ var canvas = document.getElementById('bezier');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext) {
+
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+
+
+ // Clear canvas
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ // Draw the rulers
+ ctx.beginPath();
+ ctx.strokeStyle = "black";
+
+ // Draw the Y axis
+ ctx.moveTo(cX(0), cY(0));
+ ctx.lineTo(cX(1), cY(0));
+ ctx.textAlign = "right";
+
+ for (var i = 0.1; i &lt;= 1; i = i + 0.1) {
+ ctx.moveTo(-basic_scale_size + cX(0), lY(i));
+ if ((i == 0.5) || (i &gt; 0.9)) {
+ ctx.moveTo(-2 * basic_scale_size + cX(0), lY(i));
+ ctx.fillText(Math.round(i * 10) / 10, -3 * basic_scale_size + cX(0), cY(i) + 4);
+ // Limitation the constant 4 should be font size dependant
+ }
+ ctx.lineTo(cX(0), lY(i));
+ }
+ ctx.stroke();
+ ctx.closePath();
+ ctx.beginPath();
+
+ // Draw the Y axis label
+ ctx.save();
+ ctx.rotate(-Math.PI / 2);
+ ctx.textAlign = "left";
+ ctx.fillText("Output (Value Ratio)", -cY(0), -3 * basic_scale_size + cX(0));
+ ctx.restore();
+
+ // Draw the X axis
+ ctx.moveTo(cX(0), cY(0));
+ ctx.lineTo(cX(0), cY(1));
+ ctx.textAlign = "center";
+ for (i = 0.1; i &lt;= 1; i = i + 0.1) {
+ ctx.moveTo(lX(i), basic_scale_size + cY(0));
+ if ((i == 0.5) || (i &gt; 0.9)) {
+ ctx.moveTo(lX(i), 2 * basic_scale_size + cY(0));
+ ctx.fillText(Math.round(i * 10) / 10, cX(i), 4 * basic_scale_size + cY(0));
+ // Limitation the constant 4 should be dependant of the font size
+ }
+ ctx.lineTo(lX(i), cY(0));
+ }
+
+ // Draw the X axis label
+ ctx.textAlign = "left";
+ ctx.fillText("Input (Time Duration Ratio)", cX(0), 4 * basic_scale_size + cY(0));
+ // Limitation the constant 4 should be dependant of the font size
+ ctx.stroke();
+ ctx.closePath();
+
+ // Draw the Bézier Curve
+ ctx.beginPath();
+ ctx.moveTo(cX(0), cY(0));
+ ctx.strokeStyle = 'blue';
+ ctx.bezierCurveTo(cX(x1), cY(y1), cX(x2), cY(y2), cX(1), cY(1));
+ ctx.stroke();
+ ctx.closePath();
+
+
+
+ // Draw the P2 point (with a line to P0)
+ ctx.beginPath();
+ ctx.strokeStyle = 'red';
+ ctx.moveTo(cX(x1), cY(y1));
+ ctx.lineTo(cX(0), cY(0));
+ ctx.stroke();
+ ctx.closePath();
+ ctx.beginPath();
+ ctx.moveTo(cX(x1), cY(y1));
+ ctx.arc(cX(x1), cY(y1), radius, 0, 2 * Math.PI);
+ ctx.stroke();
+ ctx.fillStyle = 'white';
+ ctx.fill();
+ ctx.closePath();
+
+
+
+ // Draw the P3 point (with a line to P1)
+ ctx.beginPath();
+ ctx.strokeStyle = 'red';
+ ctx.moveTo(cX(x2), cY(y2));
+ ctx.lineTo(cX(1), cY(1));
+ ctx.stroke();
+ ctx.closePath();
+
+ ctx.beginPath();
+ ctx.moveTo(cX(x2), cY(y2));
+ ctx.arc(cX(x2), cY(y2), radius, 0, 2 * Math.PI);
+ ctx.stroke();
+ ctx.fill();
+ ctx.closePath();
+
+ // Draw the P1(1,1) point (with dashed hints)
+ ctx.beginPath();
+ ctx.moveTo(cX(1), cY(1));
+ ctx.strokeStyle = 'lightgrey';
+ ctx.lineTo(cX(0), cY(1));
+ ctx.moveTo(cX(1), cY(1));
+ ctx.lineTo(cX(1), cY(0));
+ ctx.stroke();
+ ctx.closePath();
+
+ ctx.beginPath();
+ ctx.strokeStyle = "black";
+ ctx.fillStyle = "black";
+ ctx.arc(cX(1), cY(1), radius, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.stroke();
+ ctx.closePath();
+
+
+ // Draw the P0(0,0) point
+ ctx.beginPath();
+ ctx.arc(cX(0), cY(0), radius, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.stroke();
+ ctx.closePath();
+
+
+ } else {
+ alert('You need Safari or Firefox 1.5+ to see this demo.');
+ }
+}
+
+function mouseDown(e) {
+
+ var canvas = document.getElementById('bezier');
+
+ var x1 = cX(document.getElementById('x1').value);
+ var y1 = cY(document.getElementById('y1').value);
+
+ var x = e.pageX - canvas.offsetLeft;
+ var y = e.pageY - canvas.offsetTop;
+
+ var output = document.getElementById('output');
+ output.value = "(" + x + "," + y + ") should be (" + x1 + "," + y1 + ")";
+
+
+ if ((x1 + radius &gt;= x) &amp;&amp; (x1 - radius &lt;= x) &amp;&amp; (y1 + radius &gt;= y) &amp;&amp; (y1 - radius &lt;= y)) {
+ var output = document.getElementById('output');
+ output.value = "P1!";
+ dragSM = 1;
+ }
+
+ var x2 = cX(document.getElementById('x2').value);
+ var y2 = cY(document.getElementById('y2').value);
+
+ if ((x2 + radius &gt;= x) &amp;&amp; (x2 - radius &lt;= x) &amp;&amp; (y2 + radius &gt;= y) &amp;&amp; (y2 - radius &lt;= y)) {
+ var output = document.getElementById('output');
+ output.value = "P2!";
+ dragSM = 2;
+ }
+
+ // If we are starting a drag
+ if (dragSM != 0) {
+ canvas.onmousemove = mouseMove;
+ }
+}
+
+function mouseUp(e) {
+
+ var output = document.getElementById('output');
+ output.value = "Mouse up!";
+ dragSM = 0;
+ canvas.onmousemove = null;
+}
+
+function mouseMove(e) {
+ if (dragSM != 0) {
+ var canvas = document.getElementById('bezier');
+
+ var x = e.pageX - canvas.offsetLeft;
+ var y = e.pageY - canvas.offsetTop;
+
+ var output = document.getElementById('output');
+ output.value = "Drag!";
+
+ if (dragSM == 1) {
+ var x1 = document.getElementById('x1');
+ var y1 = document.getElementById('y1');
+ x1.value = reverseX(x);
+ x1.value = Math.round(x1.value * 10000) / 10000;
+ y1.value = reverseY(y);
+ y1.value = Math.round(y1.value * 10000) / 10000;
+ if (x1.value &lt; 0) { x1.value = 0; }
+ if (x1.value &gt; 1) { x1.value = 1; }
+ } else if (dragSM == 2) {
+ var x2 = document.getElementById('x2');
+ var y2 = document.getElementById('y2');
+ x2.value = reverseX(x);
+ x2.value = Math.round(x2.value * 10000) / 10000;
+ y2.value = reverseY(y);
+ y2.value = Math.round(y2.value * 10000) / 10000;
+ if (x2.value &lt; 0) { x2.value = 0; }
+ if (x2.value &gt; 1) { x2.value = 1; }
+ }
+ updateCanvas();
+ }
+}
+
+initCanvas();
+updateCanvas();
+ </pre>
+</div>
+
+<p>{{draft}}</p>
+
+<p><span class="seoSummary">Dies ist ein Beispielwerkzeug; es erlaubt die Bearbeitung von Bezierkurven. Es ist noch nicht wirklich nützlich, wird es aber sein!</span></p>
+
+<p>{{EmbedLiveSample("Tool", 1000, 2000)}}</p>
+</div>
diff --git a/files/de/web/css/tools/index.html b/files/de/web/css/tools/index.html
new file mode 100644
index 0000000000..f107c81ddb
--- /dev/null
+++ b/files/de/web/css/tools/index.html
@@ -0,0 +1,25 @@
+---
+title: Tools
+slug: Web/CSS/Tools
+tags:
+ - CSS
+translation_of: Web/CSS/Tools
+---
+<p>CSS bietet eine Reihe mächtiger Features, die knifflig in der Anwendung sein können oder eine Reihe von Parametern haben, sodass es hilfreich ist, diese während an ihnen gearbeitet wird, zu visualisieren. Dieses Seite bietet Links zu verschiedenen nützlichen Werkzeugen, die helfen, das CSS unter Verwendung dieser Features zu erstellen, um den Inhalt zu stylen.</p>
+
+<p>{{LandingPageListSubpages}}</p>
+
+<h2 id="Weitere_Werkzeuge">Weitere Werkzeuge</h2>
+
+<ul>
+ <li>
+ <h4 id="CSS_Animation_-_Stylie">CSS Animation - <a href="http://jeremyckahn.github.io/stylie/">Stylie</a></h4>
+ </li>
+ <li>Um die Gerätedarstellungsinformationen zu überprüfen (hilfreich in {{Glossary("Responsive Web Design")}}) - <a href="http://mydevice.io">mydevice.io</a></li>
+</ul>
+
+<h2 id="Siehe_auch">Siehe auch</h2>
+
+<ul>
+ <li><a href="/de/docs/Web/CSS">CSS</a></li>
+</ul>
diff --git a/files/de/web/css/tools/linear-gradient_generator/index.html b/files/de/web/css/tools/linear-gradient_generator/index.html
new file mode 100644
index 0000000000..bc5f7b2465
--- /dev/null
+++ b/files/de/web/css/tools/linear-gradient_generator/index.html
@@ -0,0 +1,3328 @@
+---
+title: Linear-gradient Generator
+slug: Web/CSS/Tools/Linear-gradient_Generator
+tags:
+ - CSS
+ - Werkzeuge
+translation_of: Web/CSS/Tools/Linear-gradient_Generator
+---
+<div style="display: none;">
+<h2 id="linear-gradient_generator" name="linear-gradient_generator">linear-gradient generator</h2>
+
+<h3 id="HTML_Content">HTML Content</h3>
+
+<pre class="brush: html">    &lt;div id="container"&gt;
+        &lt;div id="gradient-container" data-alpha="true"&gt;
+        &lt;/div&gt;
+
+        &lt;div id="controls"&gt;
+            &lt;div class="section"&gt;
+                &lt;div class="title"&gt; Active point &lt;/div&gt;
+                &lt;div class="property"&gt;
+                &lt;div class="ui-input-slider" data-topic="point-position" data-info="position"
+                    data-unit="px" data-min="-1000" data-value="0" data-max="1000" data-sensivity="5"&gt;&lt;/div&gt;
+                    &lt;div id="delete-point" class="button"&gt; delete point &lt;/div&gt;
+                &lt;/div&gt;
+                &lt;div class="ui-color-picker" data-topic="picker"&gt;&lt;/div&gt;
+            &lt;/div&gt;
+
+            &lt;div class="section"&gt;
+                &lt;div class="title"&gt; Active axis &lt;/div&gt;
+                &lt;div class="property"&gt;
+                    &lt;div class="name"&gt; axis unit &lt;/div&gt;
+                    &lt;div class="ui-dropdown" data-topic="axis-unit" data-selected="1"&gt;
+                        &lt;div data-value='px'&gt; pixels (px) &lt;/div&gt;
+                        &lt;div data-value='%'&gt; percentage (%) &lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div id="delete-axis" class="button"&gt; delete line &lt;/div&gt;
+                &lt;/div&gt;
+                &lt;div class="property"&gt;
+                    &lt;div class="ui-slider" data-topic="axis-rotation" data-info="rotation"
+                        data-min="-180" data-value="0" data-max="180"&gt;&lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/div&gt;
+
+            &lt;div id="tool-section" class="section"&gt;
+                &lt;div class="title"&gt; Tool settings &lt;/div&gt;
+                &lt;div class="property"&gt;
+                    &lt;div class="name"&gt; alpha background &lt;/div&gt;
+                    &lt;div id="canvas-bg"&gt;&lt;/div&gt;
+                    &lt;div id="add-axis" class="button"&gt; add line &lt;/div&gt;
+                &lt;/div&gt;
+                &lt;div id="order"&gt;
+                    &lt;div id="gradient-axes"&gt;&lt;/div&gt;
+                    &lt;div id="gradient-order"&gt;&lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+
+        &lt;div id="output"&gt;
+            &lt;div class="css-property"&gt;
+                &lt;span class="property"&gt;background:&lt;/span&gt;
+                &lt;span class="value"&gt;&lt;/span&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;</pre>
+
+<h3 id="CSS_Content">CSS Content</h3>
+
+<pre class="brush: css">/*
+ * COLOR PICKER TOOL
+ */
+
+.ui-color-picker {
+ width: 420px;
+ margin: 0;
+ border: 1px solid #DDD;
+ background-color: #FFF;
+ display: table;
+
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.ui-color-picker .picking-area {
+ width: 198px;
+ height: 198px;
+ margin: 5px;
+ border: 1px solid #DDD;
+ position: relative;
+ float: left;
+ display: table;
+}
+
+.ui-color-picker .picking-area:hover {
+ cursor: default;
+}
+
+/* HSV format - Hue-Saturation-Value(Brightness) */
+.ui-color-picker .picking-area {
+ background: url("images/picker_mask.png");
+
+ background: -moz-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
+ -moz-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
+ background: -webkit-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
+ -webkit-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
+ background: -ms-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
+ -ms-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
+ background: -o-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
+ -o-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
+
+ background-color: #F00;
+}
+
+/* HSL format - Hue-Saturation-Lightness */
+.ui-color-picker[data-mode='HSL'] .picking-area {
+ background: -moz-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
+ hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
+ -moz-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
+ background: -webkit-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
+ hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
+ -webkit-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
+ background: -ms-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
+ hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
+ -ms-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
+ background: -o-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
+ hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
+ -o-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
+ background-color: #F00;
+}
+
+.ui-color-picker .picker {
+ width: 10px;
+ height: 10px;
+ margin: -5px 0 0 -5px;
+ border-radius: 50%;
+ border: 1px solid #FFF;
+ position: absolute;
+ top: 45%;
+ left: 45%;
+}
+
+.ui-color-picker .picker:before {
+ width: 8px;
+ height: 8px;
+ content: "";
+ position: absolute;
+ border: 1px solid #999;
+ border-radius: 50%;
+}
+
+.ui-color-picker .hue,
+.ui-color-picker .alpha {
+ width: 198px;
+ height: 28px;
+ margin: 5px;
+ border: 1px solid #FFF;
+ float: left;
+}
+
+.ui-color-picker .hue {
+ background: url("images/hue_mask.png");
+ background: -moz-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
+ #00F 66.66%, #F0F 83.33%, #F00 100%);
+ background: -webkit-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
+ #00F 66.66%, #F0F 83.33%, #F00 100%);
+ background: -ms-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
+ #00F 66.66%, #F0F 83.33%, #F00 100%);
+ background: -o-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
+ #00F 66.66%, #F0F 83.33%, #F00 100%);
+}
+
+.ui-color-picker .alpha {
+ border: 1px solid #CCC;
+ background: url("images/alpha_mask.png");
+}
+
+.ui-color-picker .slider-picker {
+ width: 2px;
+ height: 100%;
+ margin: 0 0 0 -2px;
+ border: 1px solid #777;
+ background-color: #FFF;
+ position: relative;
+ top: -1px;
+}
+
+/* input HSV and RGB */
+
+.ui-color-picker .info {
+ width: 200px;
+ margin: 5px;
+ float: left;
+}
+
+.ui-color-picker .info * {
+ float: left;
+}
+
+.ui-color-picker .input {
+ width: 64px;
+ margin: 5px 2px;
+ float: left;
+}
+
+.ui-color-picker .input .name {
+ height: 20px;
+ width: 30px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 18px;
+ float: left;
+}
+
+.ui-color-picker .input input {
+ width: 30px;
+ height: 18px;
+ margin: 0;
+ padding: 0;
+ border: 1px solid #DDD;
+ text-align: center;
+ float: right;
+
+ -moz-user-select: text;
+ -webkit-user-select: text;
+ -ms-user-select: text;
+}
+
+.ui-color-picker .input[data-topic="lightness"] {
+ display: none;
+}
+
+.ui-color-picker[data-mode='HSL'] .input[data-topic="value"] {
+ display: none;
+}
+
+.ui-color-picker[data-mode='HSL'] .input[data-topic="lightness"] {
+ display: block;
+}
+
+.ui-color-picker .input[data-topic="alpha"] {
+ margin-top: 10px;
+ width: 93px;
+}
+
+.ui-color-picker .input[data-topic="alpha"] &gt; .name {
+ width: 60px;
+}
+
+.ui-color-picker .input[data-topic="alpha"] &gt; input {
+ float: right;
+}
+
+.ui-color-picker .input[data-topic="hexa"] {
+ width: auto;
+ float: right;
+ margin: 6px 8px 0 0;
+}
+
+.ui-color-picker .input[data-topic="hexa"] &gt; .name {
+ display: none;
+}
+
+.ui-color-picker .input[data-topic="hexa"] &gt; input {
+ width: 90px;
+ height: 24px;
+ padding: 2px 0;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* Preview color */
+.ui-color-picker .preview {
+ width: 95px;
+ height: 53px;
+ margin: 5px;
+ margin-top: 10px;
+ border: 1px solid #DDD;
+ background-image: url("images/alpha.png");
+ float: left;
+ position: relative;
+}
+
+.ui-color-picker .preview:before {
+ height: 100%;
+ width: 50%;
+ left: 50%;
+ top: 0;
+ content: "";
+ background: #FFF;
+ position: absolute;
+ z-index: 1;
+}
+
+.ui-color-picker .preview-color {
+ width: 100%;
+ height: 100%;
+ background-color: rgba(255, 0, 0, 0.5);
+ position: absolute;
+ z-index: 1;
+}
+
+.ui-color-picker .switch_mode {
+ width: 10px;
+ height: 20px;
+ position: relative;
+ border-radius: 5px 0 0 5px;
+ border: 1px solid #DDD;
+ background-color: #EEE;
+ left: -12px;
+ top: -1px;
+ z-index: 1;
+ transition: all 0.5s;
+}
+
+.ui-color-picker .switch_mode:hover {
+ background-color: #CCC;
+ cursor: pointer;
+}
+
+/*
+ * UI Component
+ */
+
+.ui-input-slider {
+ height: 20px;
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+ -moz-user-select: none;
+ user-select: none;
+}
+
+.ui-input-slider * {
+ float: left;
+ height: 100%;
+}
+
+/* Input Slider */
+
+.ui-input-slider &gt; input {
+ margin: 0;
+ padding: 0;
+ width: 50px;
+ text-align: center;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.ui-input-slider-info {
+ width: 90px;
+ padding: 0px 10px 0px 0px;
+ text-align: right;
+ text-transform: lowercase;
+ line-height: inherit;
+}
+
+.ui-input-slider-left, .ui-input-slider-right {
+ width: 16px;
+ cursor: pointer;
+ background: url("arrows.png") center left no-repeat;
+}
+
+.ui-input-slider-right {
+ background: url("arrows.png") center right no-repeat;
+}
+
+.ui-input-slider-name {
+ width: 90px;
+ padding: 0 10px 0 0;
+ text-align: right;
+ text-transform: lowercase;
+}
+
+.ui-input-slider-btn-set {
+ width: 25px;
+ background-color: #2C9FC9;
+ border-radius: 5px;
+ color: #FFF;
+ font-weight: bold;
+ line-height: 14px;
+ text-align: center;
+}
+
+.ui-input-slider-btn-set:hover {
+ background-color: #379B4A;
+ cursor: pointer;
+}
+
+/*
+ * UI Slider
+ */
+
+.ui-slider {
+ height: 20px;
+ margin: 10px 0;
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+ -moz-user-select: none;
+ user-select: none;
+}
+
+.ui-slider &gt; * {
+ float: left;
+ height: 100%;
+ line-height: 100%;
+}
+
+/* Slider */
+
+.ui-slider-slider {
+ height: 10px;
+ width: 200px;
+ margin: 4px 10px;
+ display: block;
+ border: 1px solid #999;
+ border-radius: 3px;
+ background: #EEE;
+}
+
+.ui-slider-slider:hover {
+ cursor: pointer;
+}
+
+.ui-slider-name {
+ width: 90px;
+ padding: 0 10px 0 0;
+ text-align: right;
+ text-transform: lowercase;
+}
+
+.ui-slider-pointer {
+ width: 12px;
+ height: 13px;
+ margin: 0 0 0 -7px;
+ background-color: #EEE;
+ border: 1px solid #2C9FC9;
+ border-radius: 3px;
+ position: relative;
+ top: -3px;
+ left: 0%;
+}
+
+.ui-slider-button {
+ width: 25px;
+ background-color: #2C9FC9;
+ border-radius: 3px;
+ color: #FFF;
+ font-weight: bold;
+ line-height: 14px;
+ text-align: center;
+}
+
+.ui-slider-button:hover {
+ background-color: #379B4A;
+ cursor: pointer;
+}
+
+.ui-slider &gt; input {
+ width: 50px;
+ margin: 0 10px;
+ padding: 0;
+ text-align: center;
+}
+
+/*
+ * UI DropDown
+ */
+
+/* Dropdown */
+
+.ui-dropdown {
+ height: 2em;
+ width: 120px;
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+ font-size: 12px;
+
+ background-image: url("dropdown_arrow.svg");
+ background-position: right 0.3em center;
+ background-repeat: no-repeat;
+ background-color: #359740;
+ background-size: 1.1em;
+
+ position: relative;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.ui-dropdown:hover {
+ cursor: pointer;
+ background-color: #208B20;
+}
+
+/* Dropdown Select Button */
+
+.ui-dropdown-select {
+ padding: 0 0.75em;
+ color: #FFF;
+ line-height: 2em;
+}
+
+/* Dropdown List */
+
+.ui-dropdown-list {
+ width: 100%;
+ height: 150px;
+ max-height: 150px;
+ margin: 0;
+ padding: 0 0.3em;
+
+ border: 1px solid #3490D2;
+ border-color: #208B20;
+ background: #666;
+ background-color: #EEF1F5;
+ color: #000;
+
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 100;
+
+ overflow: hidden;
+ transition: all 0.3s;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.ui-dropdown-list:hover {
+ overflow: auto;
+}
+
+.ui-dropdown-list[data-hidden='true'] {
+ height: 0 !important;
+ opacity: 0;
+ visibility: hidden;
+}
+
+.ui-dropdown[data-position='left'] .ui-dropdown-list {
+ left: -100%;
+ top: 0;
+}
+
+.ui-dropdown[data-position='right'] .ui-dropdown-list {
+ left: 100%;
+ top: 0;
+}
+
+.ui-dropdown-list &gt; div {
+ width: 80%;
+ height: 1.6em;
+ margin: 0.3em 0;
+ padding: 0.3em 10%;
+ line-height: 1.6em;
+}
+
+.ui-dropdown-list &gt; div:hover {
+ background: #3490D2;
+ color:#FFF;
+ border-radius: 2px;
+ cursor: pointer;
+}
+
+/*
+ * COLOR PICKER TOOL
+ */
+
+body {
+ width: 100%;
+ height: 100%;
+ margin: 0 auto;
+
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+body[data-dragging="true"] {
+}
+
+/**
+ * Resize Handle
+ */
+
+.resize-handle {
+ width: 10px;
+ height: 10px;
+ background: url("images/resize.png") center center no-repeat;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+}
+
+[data-resize='both']:hover {
+ cursor: nw-resize !important;
+}
+
+[data-resize='width']:hover {
+ cursor: w-resize !important;
+}
+
+[data-resize='height']:hover {
+ cursor: n-resize !important;
+}
+
+/**
+ * Main Container
+ */
+
+#container {
+ width: 1000px;
+ height: 100%;
+ display: table;
+ margin: 0 auto;
+}
+
+
+#gradient-container {
+ width: 450px;
+ height: 250px;
+ min-width: 8px;
+ min-height: 8px;
+ margin: 100px auto;
+ border: 1px solid #DDD;
+ position: relative;
+}
+
+#gradient-container[data-alpha="true"]:after {
+ content: "";
+ width: 100%;
+ height: 100%;
+ background: url('images/canvas-pattern.png');
+ position: absolute;
+ z-index: -1;
+}
+
+/**
+ * Gradient Axis
+ */
+
+.gradient-axis {
+ width: 125%;
+ height: 4px;
+ margin: -3px 0 0 0;
+ border: 1px solid #CCC;
+ position: absolute;
+ top: 50%;
+ left: 0;
+ opacity: 0.5;
+}
+
+.gradient-axis[data-active='true'] {
+ opacity: 1;
+ z-index: 1;
+}
+
+.gradient-axis:after {
+ content: "";
+ width: 25px;
+ height: 100%;
+ background-color: #CCC;
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+
+.gradient-axis .gradient-line {
+ width: 80%;
+ height: 100%;
+ margin: 0px auto;
+ position: relative;
+}
+
+.gradient-axis .gradient-line:hover {
+ cursor: pointer;
+}
+
+.gradient-axis .gradient-line:after,
+.gradient-axis .gradient-line:before {
+ content: "";
+ width: 1px;
+ height: 100px;
+ background-color: #CCC;
+ position: absolute;
+ top: -48px;
+}
+
+.gradient-axis .gradient-line:after {
+ left: -1px;
+}
+
+.gradient-axis .gradient-line:before {
+ right: -1px;
+}
+
+.gradient-axis .gradient-point {
+ width: 16px;
+ height: 16px;
+ margin: 0 0 0 -8px;
+ top: -7px;
+ border-radius: 50%;
+ background-color: #FFF;
+ border: 1px solid #999;
+ position: absolute;
+ z-index: 1;
+}
+
+.gradient-axis .gradient-point:after {
+ content: "";
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background-color: #FFF;
+ border: 1px solid #999;
+ position: absolute;
+ top: 4px;
+ left: 4px;
+}
+
+.gradient-axis .gradient-point:hover:after,
+.gradient-axis .gradient-point[data-active="true"]:after {
+ background-color: #CCC;
+}
+
+.gradient-axis .rotate-point {
+ width: 25px;
+ height: 25px;
+ position: absolute;
+ top: -10.5px;
+ right: -12px;
+}
+
+.gradient-axis[axisID='0']:after {
+ background-color: #DA5C5C;
+}
+
+.gradient-axis[axisID='1']:after {
+ background-color: #5CDA9B;
+}
+
+.gradient-axis[axisID='2']:after {
+ background-color: #5C9BDA;
+}
+
+.gradient-axis[axisID='3']:after {
+ background-color: #5C5CDA;
+}
+
+.gradient-axis[axisID='0'] path {
+ fill: #DA5C5C;
+}
+
+.gradient-axis[axisID='1'] path {
+ fill: #5CDA9B;
+}
+
+.gradient-axis[axisID='2'] path {
+ fill: #5C9BDA;
+}
+
+.gradient-axis[axisID='3'] path {
+ fill: #5C5CDA;
+}
+
+
+.gradient-axis .rotate-point:hover {
+ cursor: pointer;
+}
+
+/**
+ * Controls
+ */
+
+#controls {
+ width: 100%;
+ margin: 0 auto;
+ display: table;
+}
+
+#controls .section {
+ width: 50%;
+ padding: 10px;
+ display: table;
+ float: left;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#controls .section .title {
+ width: 90%;
+ margin: 0 0 10px 0;
+ padding: 5px;
+ border-bottom: 1px solid #DDD;
+ font-size: 18px;
+ color: #777;
+}
+
+#controls .property {
+ width: 100%;
+ height: 24px;
+ margin: 10px 0;
+ padding: 3px 0;
+ display: table;
+}
+
+#controls .property &gt; * {
+ float: left;
+}
+
+#controls .property .name {
+ width: 90px;
+ padding: 0px 10px 0px 0px;
+ text-align: right;
+ line-height: 150%;
+}
+
+/* Button */
+
+#controls .button {
+ height: 24px;
+ padding: 0 10px;
+ background-color: #379B4A;
+ border-radius: 3px;
+ font-size: 14px;
+ color: #FFF;
+ display: inline;
+ float: left;
+}
+
+#controls .button[data-state='disabled'] {
+ background-color: #CCC !important;
+ color: #777 !important;
+}
+
+#controls .button[data-state='disabled']:hover {
+ background-color: #CCC !important;
+ cursor: default !important;
+}
+
+#controls .button:hover {
+ cursor: pointer;
+ background-color: #208B20;
+}
+
+/* Active Point */
+
+.ui-input-slider {
+ height: 24px;
+ line-height: 20px;
+}
+
+#delete-point {
+ margin: 0 58px 0 0;
+ float: right !important;
+}
+
+#controls .ui-color-picker[data-topic="picker"] {
+ margin: 20px 0 0 0;
+}
+
+#controls .ui-input-slider[data-topic="axis-rotation"] {
+}
+
+#controls .ui-dropdown {
+ width: 130px;
+ height: 24px;
+}
+
+#controls .ui-dropdown-select {
+ line-height: 24px;
+}
+
+#controls .ui-dropdown-list {
+ height: 66px;
+ line-height: 2.5em;
+ overflow: hidden;
+}
+
+#delete-axis {
+ margin: 0 38px 0 0;
+ float: right !important;
+}
+
+/* Tool controls */
+
+#tool-section .property .name {
+ width: 150px;
+}
+
+#canvas-bg {
+ width: 16px;
+ height: 16px;
+ margin: 5px;
+ background: url("images/toggle-background.png") center right no-repeat;
+}
+
+#canvas-bg:hover {
+ cursor: pointer;
+}
+
+#canvas-bg[data-alpha='false'] {
+ background-position: center left;
+}
+
+#canvas-bg[data-alpha='true'] {
+ background-position: center right;
+}
+
+/* Order gradients */
+
+#order {
+ margin-left: 24px;
+}
+
+#gradient-axes {
+ width: 100%;
+ height: 30px;
+ padding: 0 0 0 15px;
+ display: table;
+ position: relative;
+}
+
+#gradient-axes .axis {
+ width: 50px;
+ height: 20px;
+ margin: 5px 0;
+ background-color: #DDD;
+ text-align: center;
+ float: left;
+ transition: all 0.3s;
+ position: absolute;
+}
+
+#gradient-axes .axis:hover {
+ margin: 2px 0;
+ height: 26px;
+ background-color: #CCC;
+ cursor: pointer;
+}
+
+#gradient-axes .axis[data-state='active'] {
+ margin: 2px 0;
+ height: 26px;
+}
+
+#gradient-axes .axis[data-state='active']:after {
+ content: "*";
+ color: #FFF;
+ padding: 3px;
+}
+
+#gradient-axes .axis[axisID='0'] {
+ background-color: #DA5C5C;
+}
+
+#gradient-axes .axis[axisID='1'] {
+ background-color: #5CDA9B;
+}
+
+#gradient-axes .axis[axisID='2'] {
+ background-color: #5C9BDA;
+}
+
+#gradient-axes .axis[axisID='3'] {
+ background-color: #5C5CDA;
+}
+
+#add-axis.button {
+ margin: 0 38px 0 0;
+ float: right;
+}
+
+#gradient-order {
+ width: 60%;
+ height: 5px;
+ margin: 5px 0 0 0;
+ overflow: visible;
+ background-color: #CCC;
+ position: relative;
+}
+
+#gradient-order:before {
+ content: "gradient order - drag to order";
+ position: absolute;
+ top: 100%;
+ color: #CCC;
+}
+
+#gradient-order:after {
+ content: "";
+ width: 24px;
+ height: 24px;
+ background: url('images/arrow.svg');
+ background-size: 24px 24px;
+ position: absolute;
+ right: -10px;
+ top: -9.5px;
+}
+
+
+/**
+ * Output
+ */
+
+#output {
+ width: 100%;
+ padding: 10px 0;
+ margin: 20px 0 50px 0;
+ border: 2px dashed #CCC;
+ border-radius: 5px;
+ display: table;
+ font-size: 13px;
+ overflow: hidden;
+
+ -moz-user-select: text;
+ -webkit-user-select: text;
+ -ms-user-select: text;
+ user-select: text;
+}
+
+#output .css-property {
+ width: 90%;
+ margin: 5px 5%;
+ color: #777;
+ position: relative;
+ float: left;
+}
+
+#output .property {
+ height: 100%;
+ width: 12%;
+ position: absolute;
+ left: 0;
+}
+
+#output .value {
+ width: 88%;
+ position: absolute;
+ white-space: pre;
+ word-wrap: break-word;
+ display: block;
+ right: 0;
+
+}
+
+
+</pre>
+
+<h3 id="JavaScript_Content">JavaScript Content</h3>
+
+<pre class="brush: js">var UIColorPicker = (function UIColorPicker() {
+ 'use strict';
+
+ function getElemById(id) {
+ return document.getElementById(id);
+ }
+
+ var subscribers = [];
+ var pickers = [];
+
+ /**
+ * RGBA Color class
+ *
+ * HSV/HSB and HSL (hue, saturation, value / brightness, lightness)
+ * @param hue 0-360
+ * @param saturation 0-100
+ * @param value 0-100
+ * @param lightness 0-100
+ */
+
+ function Color(color) {
+
+ if(color instanceof Color === true) {
+ this.copy(color);
+ return;
+ }
+
+ this.r = 0;
+ this.g = 0;
+ this.b = 0;
+ this.a = 1;
+ this.hue = 0;
+ this.saturation = 0;
+ this.value = 0;
+ this.lightness = 0;
+ this.format = 'HSV';
+ }
+
+ function RGBColor(r, g, b) {
+ var color = new Color();
+ color.setRGBA(r, g, b, 1);
+ return color;
+ }
+
+ function RGBAColor(r, g, b, a) {
+ var color = new Color();
+ color.setRGBA(r, g, b, a);
+ return color;
+ }
+
+ function HSVColor(h, s, v) {
+ var color = new Color();
+ color.setHSV(h, s, v);
+ return color;
+ }
+
+ function HSVAColor(h, s, v, a) {
+ var color = new Color();
+ color.setHSV(h, s, v);
+ color.a = a;
+ return color;
+ }
+
+ function HSLColor(h, s, l) {
+ var color = new Color();
+ color.setHSL(h, s, l);
+ return color;
+ }
+
+ function HSLAColor(h, s, l, a) {
+ var color = new Color();
+ color.setHSL(h, s, l);
+ color.a = a;
+ return color;
+ }
+
+ Color.prototype.copy = function copy(obj) {
+ if(obj instanceof Color !== true) {
+ console.log('Typeof parameter not Color');
+ return;
+ }
+
+ this.r = obj.r;
+ this.g = obj.g;
+ this.b = obj.b;
+ this.a = obj.a;
+ this.hue = obj.hue;
+ this.saturation = obj.saturation;
+ this.value = obj.value;
+ this.format = '' + obj.format;
+ this.lightness = obj.lightness;
+ };
+
+ Color.prototype.setFormat = function setFormat(format) {
+ if (format === 'HSV')
+ this.format = 'HSV';
+ if (format === 'HSL')
+ this.format = 'HSL';
+ };
+
+ /*========== Methods to set Color Properties ==========*/
+
+ Color.prototype.isValidRGBValue = function isValidRGBValue(value) {
+ return (typeof(value) === 'number' &amp;&amp; isNaN(value) === false &amp;&amp;
+ value &gt;= 0 &amp;&amp; value &lt;= 255);
+ };
+
+ Color.prototype.setRGBA = function setRGBA(red, green, blue, alpha) {
+ if (this.isValidRGBValue(red) === false ||
+ this.isValidRGBValue(green) === false ||
+ this.isValidRGBValue(blue) === false)
+ return;
+
+ this.r = red | 0;
+ this.g = green | 0;
+ this.b = blue | 0;
+
+ if (this.isValidRGBValue(alpha) === true)
+ this.a = alpha | 0;
+ };
+
+ Color.prototype.setByName = function setByName(name, value) {
+ if (name === 'r' || name === 'g' || name === 'b') {
+ if(this.isValidRGBValue(value) === false)
+ return;
+
+ this[name] = value;
+ this.updateHSX();
+ }
+ };
+
+ Color.prototype.setHSV = function setHSV(hue, saturation, value) {
+ this.hue = hue;
+ this.saturation = saturation;
+ this.value = value;
+ this.HSVtoRGB();
+ };
+
+ Color.prototype.setHSL = function setHSL(hue, saturation, lightness) {
+ this.hue = hue;
+ this.saturation = saturation;
+ this.lightness = lightness;
+ this.HSLtoRGB();
+ };
+
+ Color.prototype.setHue = function setHue(value) {
+ if (typeof(value) !== 'number' || isNaN(value) === true ||
+ value &lt; 0 || value &gt; 359)
+ return;
+ this.hue = value;
+ this.updateRGB();
+ };
+
+ Color.prototype.setSaturation = function setSaturation(value) {
+ if (typeof(value) !== 'number' || isNaN(value) === true ||
+ value &lt; 0 || value &gt; 100)
+ return;
+ this.saturation = value;
+ this.updateRGB();
+ };
+
+ Color.prototype.setValue = function setValue(value) {
+ if (typeof(value) !== 'number' || isNaN(value) === true ||
+ value &lt; 0 || value &gt; 100)
+ return;
+ this.value = value;
+ this.HSVtoRGB();
+ };
+
+ Color.prototype.setLightness = function setLightness(value) {
+ if (typeof(value) !== 'number' || isNaN(value) === true ||
+ value &lt; 0 || value &gt; 100)
+ return;
+ this.lightness = value;
+ this.HSLtoRGB();
+ };
+
+ Color.prototype.setAlpha = function setAlpha(value) {
+ if (typeof(value) !== 'number' || isNaN(value) === true ||
+ value &lt; 0 || value &gt; 1)
+ return;
+ this.a = parseFloat(value.toFixed(2));
+ };
+
+ Color.prototype.setHexa = function setHexa(value) {
+ var valid = /(^#{0,1}[0-9A-F]{6}$)|(^#{0,1}[0-9A-F]{3}$)/i.test(value);
+
+ if (valid !== true)
+ return;
+
+ if (value[0] === '#')
+ value = value.slice(1, value.length);
+
+ if (value.length === 3)
+ value = value.replace(/([0-9A-F])([0-9A-F])([0-9A-F])/i,'$1$1$2$2$3$3');
+
+ this.r = parseInt(value.substr(0, 2), 16);
+ this.g = parseInt(value.substr(2, 2), 16);
+ this.b = parseInt(value.substr(4, 2), 16);
+
+ this.alpha = 1;
+ this.RGBtoHSV();
+ };
+
+ /*========== Conversion Methods ==========*/
+
+ Color.prototype.convertToHSL = function convertToHSL() {
+ if (this.format === 'HSL')
+ return;
+
+ this.setFormat('HSL');
+ this.RGBtoHSL();
+ };
+
+ Color.prototype.convertToHSV = function convertToHSV() {
+ if (this.format === 'HSV')
+ return;
+
+ this.setFormat('HSV');
+ this.RGBtoHSV();
+ };
+
+ /*========== Update Methods ==========*/
+
+ Color.prototype.updateRGB = function updateRGB() {
+ if (this.format === 'HSV') {
+ this.HSVtoRGB();
+ return;
+ }
+
+ if (this.format === 'HSL') {
+ this.HSLtoRGB();
+ return;
+ }
+ };
+
+ Color.prototype.updateHSX = function updateHSX() {
+ if (this.format === 'HSV') {
+ this.RGBtoHSV();
+ return;
+ }
+
+ if (this.format === 'HSL') {
+ this.RGBtoHSL();
+ return;
+ }
+ };
+
+ Color.prototype.HSVtoRGB = function HSVtoRGB() {
+ var sat = this.saturation / 100;
+ var value = this.value / 100;
+ var C = sat * value;
+ var H = this.hue / 60;
+ var X = C * (1 - Math.abs(H % 2 - 1));
+ var m = value - C;
+ var precision = 255;
+
+ C = (C + m) * precision | 0;
+ X = (X + m) * precision | 0;
+ m = m * precision | 0;
+
+ if (H &gt;= 0 &amp;&amp; H &lt; 1) { this.setRGBA(C, X, m); return; }
+ if (H &gt;= 1 &amp;&amp; H &lt; 2) { this.setRGBA(X, C, m); return; }
+ if (H &gt;= 2 &amp;&amp; H &lt; 3) { this.setRGBA(m, C, X); return; }
+ if (H &gt;= 3 &amp;&amp; H &lt; 4) { this.setRGBA(m, X, C); return; }
+ if (H &gt;= 4 &amp;&amp; H &lt; 5) { this.setRGBA(X, m, C); return; }
+ if (H &gt;= 5 &amp;&amp; H &lt; 6) { this.setRGBA(C, m, X); return; }
+ };
+
+ Color.prototype.HSLtoRGB = function HSLtoRGB() {
+ var sat = this.saturation / 100;
+ var light = this.lightness / 100;
+ var C = sat * (1 - Math.abs(2 * light - 1));
+ var H = this.hue / 60;
+ var X = C * (1 - Math.abs(H % 2 - 1));
+ var m = light - C/2;
+ var precision = 255;
+
+ C = (C + m) * precision | 0;
+ X = (X + m) * precision | 0;
+ m = m * precision | 0;
+
+ if (H &gt;= 0 &amp;&amp; H &lt; 1) { this.setRGBA(C, X, m); return; }
+ if (H &gt;= 1 &amp;&amp; H &lt; 2) { this.setRGBA(X, C, m); return; }
+ if (H &gt;= 2 &amp;&amp; H &lt; 3) { this.setRGBA(m, C, X); return; }
+ if (H &gt;= 3 &amp;&amp; H &lt; 4) { this.setRGBA(m, X, C); return; }
+ if (H &gt;= 4 &amp;&amp; H &lt; 5) { this.setRGBA(X, m, C); return; }
+ if (H &gt;= 5 &amp;&amp; H &lt; 6) { this.setRGBA(C, m, X); return; }
+ };
+
+ Color.prototype.RGBtoHSV = function RGBtoHSV() {
+ var red = this.r / 255;
+ var green = this.g / 255;
+ var blue = this.b / 255;
+
+ var cmax = Math.max(red, green, blue);
+ var cmin = Math.min(red, green, blue);
+ var delta = cmax - cmin;
+ var hue = 0;
+ var saturation = 0;
+
+ if (delta) {
+ if (cmax === red ) { hue = ((green - blue) / delta); }
+ if (cmax === green ) { hue = 2 + (blue - red) / delta; }
+ if (cmax === blue ) { hue = 4 + (red - green) / delta; }
+ if (cmax) saturation = delta / cmax;
+ }
+
+ this.hue = 60 * hue | 0;
+ if (this.hue &lt; 0) this.hue += 360;
+ this.saturation = (saturation * 100) | 0;
+ this.value = (cmax * 100) | 0;
+ };
+
+ Color.prototype.RGBtoHSL = function RGBtoHSL() {
+ var red = this.r / 255;
+ var green = this.g / 255;
+ var blue = this.b / 255;
+
+ var cmax = Math.max(red, green, blue);
+ var cmin = Math.min(red, green, blue);
+ var delta = cmax - cmin;
+ var hue = 0;
+ var saturation = 0;
+ var lightness = (cmax + cmin) / 2;
+ var X = (1 - Math.abs(2 * lightness - 1));
+
+ if (delta) {
+ if (cmax === red ) { hue = ((green - blue) / delta); }
+ if (cmax === green ) { hue = 2 + (blue - red) / delta; }
+ if (cmax === blue ) { hue = 4 + (red - green) / delta; }
+ if (cmax) saturation = delta / X;
+ }
+
+ this.hue = 60 * hue | 0;
+ if (this.hue &lt; 0) this.hue += 360;
+ this.saturation = (saturation * 100) | 0;
+ this.lightness = (lightness * 100) | 0;
+ };
+
+ /*========== Get Methods ==========*/
+
+ Color.prototype.getHexa = function getHexa() {
+ var r = this.r.toString(16);
+ var g = this.g.toString(16);
+ var b = this.b.toString(16);
+ if (this.r &lt; 16) r = '0' + r;
+ if (this.g &lt; 16) g = '0' + g;
+ if (this.b &lt; 16) b = '0' + b;
+ var value = '#' + r + g + b;
+ return value.toUpperCase();
+ };
+
+ Color.prototype.getRGBA = function getRGBA() {
+
+ var rgb = '(' + this.r + ', ' + this.g + ', ' + this.b;
+ var a = '';
+ var v = '';
+ var x = parseFloat(this.a);
+ if (x !== 1) {
+ a = 'a';
+ v = ', ' + x;
+ }
+
+ var value = 'rgb' + a + rgb + v + ')';
+ return value;
+ };
+
+ Color.prototype.getHSLA = function getHSLA() {
+ if (this.format === 'HSV') {
+ var color = new Color(this);
+ color.setFormat('HSL');
+ color.updateHSX();
+ return color.getHSLA();
+ }
+
+ var a = '';
+ var v = '';
+ var hsl = '(' + this.hue + ', ' + this.saturation + '%, ' + this.lightness +'%';
+ var x = parseFloat(this.a);
+ if (x !== 1) {
+ a = 'a';
+ v = ', ' + x;
+ }
+
+ var value = 'hsl' + a + hsl + v + ')';
+ return value;
+ };
+
+ Color.prototype.getColor = function getColor() {
+ if (this.a | 0 === 1)
+ return this.getHexa();
+ return this.getRGBA();
+ };
+
+ /*=======================================================================*/
+ /*=======================================================================*/
+
+ /*========== Capture Mouse Movement ==========*/
+
+ var setMouseTracking = function setMouseTracking(elem, callback) {
+ elem.addEventListener('mousedown', function(e) {
+ callback(e);
+ document.addEventListener('mousemove', callback);
+ });
+
+ document.addEventListener('mouseup', function(e) {
+ document.removeEventListener('mousemove', callback);
+ });
+ };
+
+ /*====================*/
+ // Color Picker Class
+ /*====================*/
+
+ function ColorPicker(node) {
+ this.color = new Color();
+ this.node = node;
+ this.subscribers = [];
+
+ var type = this.node.getAttribute('data-mode');
+ var topic = this.node.getAttribute('data-topic');
+
+ this.topic = topic;
+ this.picker_mode = (type === 'HSL') ? 'HSL' : 'HSV';
+ this.color.setFormat(this.picker_mode);
+
+ this.createPickingArea();
+ this.createHueArea();
+
+ this.newInputComponent('H', 'hue', this.inputChangeHue.bind(this));
+ this.newInputComponent('S', 'saturation', this.inputChangeSaturation.bind(this));
+ this.newInputComponent('V', 'value', this.inputChangeValue.bind(this));
+ this.newInputComponent('L', 'lightness', this.inputChangeLightness.bind(this));
+
+ this.createAlphaArea();
+
+ this.newInputComponent('R', 'red', this.inputChangeRed.bind(this));
+ this.newInputComponent('G', 'green', this.inputChangeGreen.bind(this));
+ this.newInputComponent('B', 'blue', this.inputChangeBlue.bind(this));
+
+ this.createPreviewBox();
+ this.createChangeModeButton();
+
+ this.newInputComponent('alpha', 'alpha', this.inputChangeAlpha.bind(this));
+ this.newInputComponent('hexa', 'hexa', this.inputChangeHexa.bind(this));
+
+ this.setColor(this.color);
+ pickers[topic] = this;
+ }
+
+ /*************************************************************************/
+ // Function for generating the color-picker
+ /*************************************************************************/
+
+ ColorPicker.prototype.createPickingArea = function createPickingArea() {
+ var area = document.createElement('div');
+ var picker = document.createElement('div');
+
+ area.className = 'picking-area';
+ picker.className = 'picker';
+
+ this.picking_area = area;
+ this.color_picker = picker;
+ setMouseTracking(area, this.updateColor.bind(this));
+
+ area.appendChild(picker);
+ this.node.appendChild(area);
+ };
+
+ ColorPicker.prototype.createHueArea = function createHueArea() {
+ var area = document.createElement('div');
+ var picker = document.createElement('div');
+
+ area.className = 'hue';
+ picker.className ='slider-picker';
+
+ this.hue_area = area;
+ this.hue_picker = picker;
+ setMouseTracking(area, this.updateHueSlider.bind(this));
+
+ area.appendChild(picker);
+ this.node.appendChild(area);
+ };
+
+ ColorPicker.prototype.createAlphaArea = function createAlphaArea() {
+ var mask = document.createElement('div');
+ var picker = document.createElement('div');
+
+ mask.className = 'alpha';
+ picker.className = 'slider-picker';
+
+ this.alpha_mask = mask;
+ this.alpha_picker = picker;
+ setMouseTracking(mask, this.updateAlphaSlider.bind(this));
+
+ mask.appendChild(picker);
+ this.node.appendChild(mask);
+ };
+
+ ColorPicker.prototype.createPreviewBox = function createPreviewBox(e) {
+ var preview_box = document.createElement('div');
+ var preview_color = document.createElement('div');
+
+ preview_box.className = 'preview';
+ preview_color.className = 'preview-color';
+
+ this.preview_color = preview_color;
+
+ preview_box.appendChild(preview_color);
+ this.node.appendChild(preview_box);
+ };
+
+ ColorPicker.prototype.newInputComponent = function newInputComponent(title, topic, onChangeFunc) {
+ var wrapper = document.createElement('div');
+ var input = document.createElement('input');
+ var info = document.createElement('span');
+
+ wrapper.className = 'input';
+ wrapper.setAttribute('data-topic', topic);
+ info.textContent = title;
+ info.className = 'name';
+ input.setAttribute('type', 'text');
+
+ wrapper.appendChild(info);
+ wrapper.appendChild(input);
+ this.node.appendChild(wrapper);
+
+ input.addEventListener('change', onChangeFunc);
+ input.addEventListener('click', function() {
+ this.select();
+ });
+
+ this.subscribe(topic, function(value) {
+ input.value = value;
+ });
+ };
+
+ ColorPicker.prototype.createChangeModeButton = function createChangeModeButton() {
+
+ var button = document.createElement('div');
+ button.className = 'switch_mode';
+ button.addEventListener('click', function() {
+ if (this.picker_mode === 'HSV')
+ this.setPickerMode('HSL');
+ else
+ this.setPickerMode('HSV');
+
+ }.bind(this));
+
+ this.node.appendChild(button);
+ };
+
+ /*************************************************************************/
+ // Updates properties of UI elements
+ /*************************************************************************/
+
+ ColorPicker.prototype.updateColor = function updateColor(e) {
+ var x = e.pageX - this.picking_area.offsetLeft;
+ var y = e.pageY - this.picking_area.offsetTop;
+
+ // width and height should be the same
+ var size = this.picking_area.clientWidth;
+
+ if (x &gt; size) x = size;
+ if (y &gt; size) y = size;
+ if (x &lt; 0) x = 0;
+ if (y &lt; 0) y = 0;
+
+ var value = 100 - (y * 100 / size) | 0;
+ var saturation = x * 100 / size | 0;
+
+ if (this.picker_mode === 'HSV')
+ this.color.setHSV(this.color.hue, saturation, value);
+ if (this.picker_mode === 'HSL')
+ this.color.setHSL(this.color.hue, saturation, value);
+
+ this.color_picker.style.left = x + 'px';
+ this.color_picker.style.top = y + 'px';
+
+ this.updateAlphaGradient();
+ this.updatePreviewColor();
+
+ this.notify('value', value);
+ this.notify('lightness', value);
+ this.notify('saturation', saturation);
+
+ this.notify('red', this.color.r);
+ this.notify('green', this.color.g);
+ this.notify('blue', this.color.b);
+ this.notify('hexa', this.color.getHexa());
+
+ notify(this.topic, this.color);
+ };
+
+ ColorPicker.prototype.updateHueSlider = function updateHueSlider(e) {
+ var x = e.pageX - this.hue_area.offsetLeft;
+ var width = this.hue_area.clientWidth;
+
+ if (x &lt; 0) x = 0;
+ if (x &gt; width) x = width;
+
+ var hue = ((359 * x) / width) | 0;
+
+ this.updateSliderPosition(this.hue_picker, x - 1);
+ this.setHue(hue);
+ };
+
+ ColorPicker.prototype.updateAlphaSlider = function updateAlphaSlider(e) {
+ var x = e.pageX - this.alpha_mask.offsetLeft;
+ var width = this.alpha_mask.clientWidth;
+
+ if (x &lt; 0) x = 0;
+ if (x &gt; width) x = width;
+
+ this.color.a = (x / width).toFixed(2);
+
+ this.updateSliderPosition(this.alpha_picker, x - 1);
+ this.updatePreviewColor();
+
+ this.notify('alpha', this.color.a);
+ notify(this.topic, this.color);
+ };
+
+ ColorPicker.prototype.setHue = function setHue(value) {
+ this.color.setHue(value);
+
+ this.updatePickerBackground();
+ this.updateAlphaGradient();
+ this.updatePreviewColor();
+
+ this.notify('red', this.color.r);
+ this.notify('green', this.color.g);
+ this.notify('blue', this.color.b);
+ this.notify('hexa', this.color.getHexa());
+ this.notify('hue', this.color.hue);
+
+ notify(this.topic, this.color);
+ };
+
+ // Updates when one of Saturation/Value/Lightness changes
+ ColorPicker.prototype.updateSLV = function updateSLV() {
+ this.updatePickerPosition();
+ this.updateAlphaGradient();
+ this.updatePreviewColor();
+
+ this.notify('red', this.color.r);
+ this.notify('green', this.color.g);
+ this.notify('blue', this.color.b);
+ this.notify('hexa', this.color.getHexa());
+
+ notify(this.topic, this.color);
+ };
+
+ /*************************************************************************/
+ // Update positions of various UI elements
+ /*************************************************************************/
+
+ ColorPicker.prototype.updatePickerPosition = function updatePickerPosition() {
+ var size = this.picking_area.clientWidth;
+ var value = 0;
+
+ if (this.picker_mode === 'HSV')
+ value = this.color.value;
+ if (this.picker_mode === 'HSL')
+ value = this.color.lightness;
+
+ var x = (this.color.saturation * size / 100) | 0;
+ var y = size - (value * size / 100) | 0;
+
+ this.color_picker.style.left = x + 'px';
+ this.color_picker.style.top = y + 'px';
+ };
+
+ ColorPicker.prototype.updateSliderPosition = function updateSliderPosition(elem, pos) {
+ elem.style.left = pos + 'px';
+ };
+
+ ColorPicker.prototype.updateHuePicker = function updateHuePicker() {
+ var size = this.hue_area.clientWidth;
+ var pos = (this.color.hue * size / 360 ) | 0;
+ this.hue_picker.style.left = pos + 'px';
+ };
+
+ ColorPicker.prototype.updateAlphaPicker = function updateAlphaPicker() {
+ var size = this.alpha_mask.clientWidth;
+ var pos = (this.color.a * size) | 0;
+ this.alpha_picker.style.left = pos + 'px';
+ };
+
+ /*************************************************************************/
+ // Update background colors
+ /*************************************************************************/
+
+ ColorPicker.prototype.updatePickerBackground = function updatePickerBackground() {
+ var nc = new Color(this.color);
+ nc.setHSV(nc.hue, 100, 100);
+ this.picking_area.style.backgroundColor = nc.getHexa();
+ };
+
+ ColorPicker.prototype.updateAlphaGradient = function updateAlphaGradient() {
+ this.alpha_mask.style.backgroundColor = this.color.getHexa();
+ };
+
+ ColorPicker.prototype.updatePreviewColor = function updatePreviewColor() {
+ this.preview_color.style.backgroundColor = this.color.getColor();
+ };
+
+ /*************************************************************************/
+ // Update input elements
+ /*************************************************************************/
+
+ ColorPicker.prototype.inputChangeHue = function inputChangeHue(e) {
+ var value = parseInt(e.target.value);
+ this.setHue(value);
+ this.updateHuePicker();
+ };
+
+ ColorPicker.prototype.inputChangeSaturation = function inputChangeSaturation(e) {
+ var value = parseInt(e.target.value);
+ this.color.setSaturation(value);
+ e.target.value = this.color.saturation;
+ this.updateSLV();
+ };
+
+ ColorPicker.prototype.inputChangeValue = function inputChangeValue(e) {
+ var value = parseInt(e.target.value);
+ this.color.setValue(value);
+ e.target.value = this.color.value;
+ this.updateSLV();
+ };
+
+ ColorPicker.prototype.inputChangeLightness = function inputChangeLightness(e) {
+ var value = parseInt(e.target.value);
+ this.color.setLightness(value);
+ e.target.value = this.color.lightness;
+ this.updateSLV();
+ };
+
+ ColorPicker.prototype.inputChangeRed = function inputChangeRed(e) {
+ var value = parseInt(e.target.value);
+ this.color.setByName('r', value);
+ e.target.value = this.color.r;
+ this.setColor(this.color);
+ };
+
+ ColorPicker.prototype.inputChangeGreen = function inputChangeGreen(e) {
+ var value = parseInt(e.target.value);
+ this.color.setByName('g', value);
+ e.target.value = this.color.g;
+ this.setColor(this.color);
+ };
+
+ ColorPicker.prototype.inputChangeBlue = function inputChangeBlue(e) {
+ var value = parseInt(e.target.value);
+ this.color.setByName('b', value);
+ e.target.value = this.color.b;
+ this.setColor(this.color);
+ };
+
+ ColorPicker.prototype.inputChangeAlpha = function inputChangeAlpha(e) {
+ var value = parseFloat(e.target.value);
+
+ if (typeof value === 'number' &amp;&amp; isNaN(value) === false &amp;&amp;
+ value &gt;= 0 &amp;&amp; value &lt;= 1)
+ this.color.a = value.toFixed(2);
+
+ e.target.value = this.color.a;
+ this.updateAlphaPicker();
+ this.updatePreviewColor();
+ };
+
+ ColorPicker.prototype.inputChangeHexa = function inputChangeHexa(e) {
+ var value = e.target.value;
+ this.color.setHexa(value);
+ this.setColor(this.color);
+ };
+
+ /*************************************************************************/
+ // Internal Pub/Sub
+ /*************************************************************************/
+
+ ColorPicker.prototype.subscribe = function subscribe(topic, callback) {
+ this.subscribers[topic] = callback;
+ };
+
+ ColorPicker.prototype.notify = function notify(topic, value) {
+ if (this.subscribers[topic])
+ this.subscribers[topic](value);
+ };
+
+ /*************************************************************************/
+ // Set Picker Properties
+ /*************************************************************************/
+
+ ColorPicker.prototype.setColor = function setColor(color) {
+ if(color instanceof Color !== true) {
+ console.log('Typeof parameter not Color');
+ return;
+ }
+
+ if (color.format !== this.picker_mode) {
+ color.setFormat(this.picker_mode);
+ color.updateHSX();
+ }
+
+ this.color.copy(color);
+ this.updateHuePicker();
+ this.updatePickerPosition();
+ this.updatePickerBackground();
+ this.updateAlphaPicker();
+ this.updatePreviewColor();
+ this.updateAlphaGradient();
+
+ this.notify('red', this.color.r);
+ this.notify('green', this.color.g);
+ this.notify('blue', this.color.b);
+
+ this.notify('hue', this.color.hue);
+ this.notify('saturation', this.color.saturation);
+ this.notify('value', this.color.value);
+ this.notify('lightness', this.color.lightness);
+
+ this.notify('alpha', this.color.a);
+ this.notify('hexa', this.color.getHexa());
+ notify(this.topic, this.color);
+ };
+
+ ColorPicker.prototype.setPickerMode = function setPickerMode(mode) {
+ if (mode !== 'HSV' &amp;&amp; mode !== 'HSL')
+ return;
+
+ this.picker_mode = mode;
+ this.node.setAttribute('data-mode', this.picker_mode);
+ this.setColor(this.color);
+ };
+
+ /*************************************************************************/
+ // UNUSED
+ /*************************************************************************/
+
+ var setPickerMode = function setPickerMode(topic, mode) {
+ if (pickers[topic])
+ pickers[topic].setPickerMode(mode);
+ };
+
+ var setColor = function setColor(topic, color) {
+ if (pickers[topic])
+ pickers[topic].setColor(color);
+ };
+
+ var getColor = function getColor(topic) {
+ if (pickers[topic])
+ return new Color(pickers[topic].color);
+ };
+
+ var subscribe = function subscribe(topic, callback) {
+ if (subscribers[topic] === undefined)
+ subscribers[topic] = [];
+
+ subscribers[topic].push(callback);
+ };
+
+ var unsubscribe = function unsubscribe(callback) {
+ subscribers.indexOf(callback);
+ subscribers.splice(index, 1);
+ };
+
+ var notify = function notify(topic, value) {
+ if (subscribers[topic] === undefined || subscribers[topic].length === 0)
+ return;
+
+ var color = new Color(value);
+ for (var i in subscribers[topic])
+ subscribers[topic][i](color);
+ };
+
+ var init = function init() {
+ var elem = document.querySelectorAll('.ui-color-picker');
+ var size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ new ColorPicker(elem[i]);
+ };
+
+ return {
+ init : init,
+ Color : Color,
+ RGBColor : RGBColor,
+ RGBAColor : RGBAColor,
+ HSVColor : HSVColor,
+ HSVAColor : HSVAColor,
+ HSLColor : HSLColor,
+ HSLAColor : HSLAColor,
+ setColor : setColor,
+ getColor : getColor,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe,
+ setPickerMode : setPickerMode
+ };
+
+})();
+
+/**
+ * UI-DropDown Select
+ */
+
+var DropDownManager = (function DropdownManager() {
+ 'use strict';
+
+ var subscribers = {};
+ var dropdowns = [];
+ var active = null;
+
+ var visbility = ["hidden", "visible"];
+
+ var DropDown = function DropDown(node) {
+ var topic = node.getAttribute('data-topic');
+ var label = node.getAttribute('data-label');
+ var selected = node.getAttribute('data-selected') | 0;
+
+ var select = document.createElement('div');
+ var list = document.createElement('div');
+ var uval = 0;
+ var option = null;
+ var option_value = null;
+
+ list.className = 'ui-dropdown-list';
+ select.className = 'ui-dropdown-select';
+
+ while (node.firstElementChild !== null) {
+ option = node.firstElementChild;
+ option_value = option.getAttribute('data-value');
+
+ if (option_value === null)
+ option.setAttribute('data-value', uval);
+
+ list.appendChild(node.firstElementChild);
+ uval++;
+ }
+
+ node.appendChild(select);
+ node.appendChild(list);
+
+ select.onclick = this.toggle.bind(this);
+ list.onclick = this.updateValue.bind(this);
+ document.addEventListener('click', clickOut);
+
+ this.state = 0;
+ this.time = 0;
+ this.dropmenu = list;
+ this.select = select;
+ this.toggle(false);
+ this.value = {};
+ this.topic = topic;
+
+ if (label)
+ select.textContent = label;
+ else
+ this.setNodeValue(list.children[selected]);
+
+ dropdowns[topic] = this;
+
+ };
+
+ DropDown.prototype.toggle = function toggle(state) {
+ if (typeof(state) === 'boolean')
+ this.state = state === false ? 0 : 1;
+ else
+ this.state = 1 ^ this.state;
+
+ if (active !== this) {
+ if (active)
+ active.toggle(false);
+ active = this;
+ }
+
+ if (this.state === 0)
+ this.dropmenu.setAttribute('data-hidden', 'true');
+ else
+ this.dropmenu.removeAttribute('data-hidden');
+
+ };
+
+ DropDown.prototype.updateValue = function updateValue(e) {
+
+ if (Date.now() - this.time &lt; 500)
+ return;
+
+ if (e.target.className !== "ui-dropdown-list") {
+ this.setNodeValue(e.target);
+ this.toggle(false);
+ }
+
+ this.time = Date.now();
+ };
+
+ DropDown.prototype.setNodeValue = function setNodeValue(node, send_notify) {
+ this.value['name'] = node.textContent;
+ this.value['value'] = node.getAttribute('data-value');
+
+ this.select.textContent = node.textContent;
+ this.select.setAttribute('data-value', this.value['value']);
+
+ if (send_notify !== false)
+ notify.call(this);
+ };
+
+ var clickOut = function clickOut(e) {
+ if (active.state === 0 ||
+ e.target === active.dropmenu ||
+ e.target === active.select)
+ return;
+
+ active.toggle(false);
+ };
+
+ var createDropDown = function createDropDown(topic, options) {
+
+ var dropdown = document.createElement('div');
+ dropdown.setAttribute('data-topic', topic);
+ dropdown.className = 'ui-dropdown';
+
+ for (var i in options) {
+ var x = document.createElement('div');
+ x.setAttribute('data-value', i);
+ x.textContent = options[i];
+ dropdown.appendChild(x);
+ }
+
+ new DropDown(dropdown);
+
+ return dropdown;
+ };
+
+ var setValue = function setValue(topic, index, send_notify) {
+ if (dropdowns[topic] === undefined ||
+ index &gt;= dropdowns[topic].dropmenu.children.length)
+ return;
+
+ dropdowns[topic].setNodeValue(dropdowns[topic].dropmenu.children[index], send_notify);
+ };
+
+ var subscribe = function subscribe(topic, callback) {
+ if (subscribers[topic] === undefined)
+ subscribers[topic] = [];
+ subscribers[topic].push(callback);
+ };
+
+ var unsubscribe = function unsubscribe(topic, callback) {
+ var index = subscribers[topic].indexOf(callback);
+ subscribers[topic].splice(index, 1);
+ };
+
+ var notify = function notify() {
+ if (subscribers[this.topic] === undefined)
+ return;
+
+ for (var i in subscribers[this.topic]) {
+ subscribers[this.topic][i](this.value);
+ }
+ };
+
+ var init = function init() {
+ var elem, size;
+
+ elem = document.querySelectorAll('.ui-dropdown');
+ size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ new DropDown(elem[i]);
+
+ };
+
+ return {
+ init : init,
+ setValue : setValue,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe,
+ createDropDown : createDropDown
+ };
+
+})();
+
+/**
+ * UI-SlidersManager
+ */
+
+var InputSliderManager = (function InputSliderManager() {
+ 'use strict';
+
+ var subscribers = {};
+ var sliders = [];
+
+ var InputComponent = function InputComponent(obj) {
+ var input = document.createElement('input');
+ input.setAttribute('type', 'text');
+ input.style.width = 50 + obj.precision * 10 + 'px';
+
+ input.addEventListener('click', function(e) {
+ this.select();
+ });
+
+ input.addEventListener('change', function(e) {
+ var value = parseFloat(e.target.value);
+
+ if (isNaN(value) === true)
+ setValue(obj.topic, obj.value);
+ else
+ setValue(obj.topic, value);
+ });
+
+ return input;
+ };
+
+ var SliderComponent = function SliderComponent(obj, sign) {
+ var slider = document.createElement('div');
+ var startX = null;
+ var start_value = 0;
+
+ slider.addEventListener("click", function(e) {
+ document.removeEventListener("mousemove", sliderMotion);
+ setValue(obj.topic, obj.value + obj.step * sign);
+ });
+
+ slider.addEventListener("mousedown", function(e) {
+ startX = e.clientX;
+ start_value = obj.value;
+ document.body.style.cursor = "e-resize";
+
+ document.addEventListener("mouseup", slideEnd);
+ document.addEventListener("mousemove", sliderMotion);
+ });
+
+ var slideEnd = function slideEnd(e) {
+ document.removeEventListener("mousemove", sliderMotion);
+ document.body.style.cursor = "auto";
+ slider.style.cursor = "pointer";
+ };
+
+ var sliderMotion = function sliderMotion(e) {
+ slider.style.cursor = "e-resize";
+ var delta = (e.clientX - startX) / obj.sensivity | 0;
+ var value = delta * obj.step + start_value;
+ setValue(obj.topic, value);
+ };
+
+ return slider;
+ };
+
+ var InputSlider = function(node) {
+ var min = parseFloat(node.getAttribute('data-min'));
+ var max = parseFloat(node.getAttribute('data-max'));
+ var step = parseFloat(node.getAttribute('data-step'));
+ var value = parseFloat(node.getAttribute('data-value'));
+ var topic = node.getAttribute('data-topic');
+ var unit = node.getAttribute('data-unit');
+ var name = node.getAttribute('data-info');
+ var sensivity = node.getAttribute('data-sensivity') | 0;
+ var precision = node.getAttribute('data-precision') | 0;
+
+ this.min = isNaN(min) ? 0 : min;
+ this.max = isNaN(max) ? 100 : max;
+ this.precision = precision &gt;= 0 ? precision : 0;
+ this.step = step &lt; 0 || isNaN(step) ? 1 : step.toFixed(precision);
+ this.topic = topic;
+ this.node = node;
+ this.unit = unit === null ? '' : unit;
+ this.sensivity = sensivity &gt; 0 ? sensivity : 5;
+ value = isNaN(value) ? this.min : value;
+
+ var input = new InputComponent(this);
+ var slider_left = new SliderComponent(this, -1);
+ var slider_right = new SliderComponent(this, 1);
+
+ slider_left.className = 'ui-input-slider-left';
+ slider_right.className = 'ui-input-slider-right';
+
+ if (name) {
+ var info = document.createElement('span');
+ info.className = 'ui-input-slider-info';
+ info.textContent = name;
+ node.appendChild(info);
+ }
+
+ node.appendChild(slider_left);
+ node.appendChild(input);
+ node.appendChild(slider_right);
+
+ this.input = input;
+ sliders[topic] = this;
+ setValue(topic, value);
+ };
+
+ InputSlider.prototype.setInputValue = function setInputValue() {
+ this.input.value = this.value.toFixed(this.precision) + this.unit;
+ };
+
+ var setValue = function setValue(topic, value, send_notify) {
+ var slider = sliders[topic];
+ if (slider === undefined)
+ return;
+
+ value = parseFloat(value.toFixed(slider.precision));
+
+ if (value &gt; slider.max) value = slider.max;
+ if (value &lt; slider.min) value = slider.min;
+
+ slider.value = value;
+ slider.node.setAttribute('data-value', value);
+
+ slider.setInputValue();
+
+ if (send_notify === false)
+ return;
+
+ notify.call(slider);
+ };
+
+ var setMax = function setMax(topic, value) {
+ var slider = sliders[topic];
+ if (slider === undefined)
+ return;
+
+ slider.max = value;
+ setValue(topic, slider.value);
+ };
+
+ var setMin = function setMin(topic, value) {
+ var slider = sliders[topic];
+ if (slider === undefined)
+ return;
+
+ slider.min = value;
+ setValue(topic, slider.value);
+ };
+
+ var setUnit = function setUnit(topic, unit, send_notify) {
+ var slider = sliders[topic];
+ if (slider === undefined)
+ return;
+
+ slider.unit = unit;
+ setValue(topic, slider.value, send_notify);
+ };
+
+ var setStep = function setStep(topic, value) {
+ var slider = sliders[topic];
+ if (slider === undefined)
+ return;
+
+ slider.step = parseFloat(value);
+ setValue(topic, slider.value);
+ };
+
+ var setPrecision = function setPrecision(topic, value) {
+ var slider = sliders[topic];
+ if (slider === undefined)
+ return;
+
+ value = value | 0;
+ slider.precision = value;
+
+ var step = parseFloat(slider.step.toFixed(value));
+ if (step === 0)
+ slider.step = 1 / Math.pow(10, value);
+
+ setValue(topic, slider.value);
+ };
+
+ var setSensivity = function setSensivity(topic, value) {
+ var slider = sliders[topic];
+ if (slider === undefined)
+ return;
+
+ value = value | 0;
+
+ slider.sensivity = value &gt; 0 ? value : 5;
+ };
+
+ var getNode = function getNode(topic) {
+ return sliders[topic].node;
+ };
+
+ var getPrecision = function getPrecision(topic) {
+ return sliders[topic].precision;
+ };
+
+ var getStep = function getStep(topic) {
+ return sliders[topic].step;
+ };
+
+ var subscribe = function subscribe(topic, callback) {
+ if (subscribers[topic] === undefined)
+ subscribers[topic] = [];
+ subscribers[topic].push(callback);
+ };
+
+ var unsubscribe = function unsubscribe(topic, callback) {
+ subscribers[topic].indexOf(callback);
+ subscribers[topic].splice(index, 1);
+ };
+
+ var notify = function notify() {
+ if (subscribers[this.topic] === undefined)
+ return;
+ for (var i = 0; i &lt; subscribers[this.topic].length; i++)
+ subscribers[this.topic][i](this.value);
+ };
+
+ var createSlider = function createSlider(topic, label) {
+ var slider = document.createElement('div');
+ slider.className = 'ui-input-slider';
+ slider.setAttribute('data-topic', topic);
+
+ if (label !== undefined)
+ slider.setAttribute('data-info', label);
+
+ new InputSlider(slider);
+ return slider;
+ };
+
+ var init = function init() {
+ var elem = document.querySelectorAll('.ui-input-slider');
+ var size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ new InputSlider(elem[i]);
+ };
+
+ return {
+ init : init,
+ setMax : setMax,
+ setMin : setMin,
+ setUnit : setUnit,
+ setStep : setStep,
+ getNode : getNode,
+ getStep : getStep,
+ setValue : setValue,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe,
+ setPrecision : setPrecision,
+ setSensivity : setSensivity,
+ getPrecision : getPrecision,
+ createSlider : createSlider,
+ };
+
+})();
+
+/**
+ * UI-SlidersManager
+ */
+
+var SliderManager = (function SliderManager() {
+ 'use strict';
+
+ var subscribers = {};
+ var sliders = [];
+
+ function trackMouse(elem, callback, startFunc, endFunc) {
+ startFunc = startFunc || function(e) {};
+ endFunc = endFunc || function(e) {};
+
+ elem.addEventListener('mousedown', function(e) {
+ e.preventDefault();
+ startFunc(e);
+
+ document.addEventListener('mousemove', callback);
+ document.addEventListener('mouseup', function up(e) {
+ document.removeEventListener('mousemove', callback);
+ document.removeEventListener('mouseup', up);
+ endFunc(e);
+ });
+ });
+
+ elem.addEventListener('click', function(e) {
+ e.stopPropagation();
+ });
+ }
+
+ var Slider = function(node) {
+ var topic = node.getAttribute('data-topic');
+ var info = node.getAttribute('data-info');
+ var unit = node.getAttribute('data-unit');
+ var min = node.getAttribute('data-min') | 0;
+ var max = node.getAttribute('data-max') | 0;
+ var step = node.getAttribute('data-step') | 0;
+ var value = node.getAttribute('data-value') | 0;
+ var snap = node.getAttribute('data-snap');
+
+ this.min = min;
+ this.max = max &gt; 0 ? max : 100;
+ this.step = step === 0 ? 1 : step;
+ this.value = value &lt;= max &amp;&amp; value &gt;= min ? value : (min + max) / 2 | 0;
+ this.snap = snap === "true" ? true : false;
+ this.topic = topic;
+ this.unit = unit;
+
+ var name = document.createElement('div');
+ var slider = document.createElement('div');
+ var pointer = document.createElement('div');
+
+ name.className = 'ui-slider-name';
+ name.textContent = info;
+
+ slider.className = 'ui-slider-slider';
+ pointer.className = 'ui-slider-pointer';
+
+ node.appendChild(name);
+ slider.appendChild(pointer);
+
+ this.pointer = pointer;
+ this.slider = slider;
+ this.node = node;
+
+ this.createSetButton('-', this.decrement.bind(this));
+ node.appendChild(slider);
+ this.createSetButton('+', this.increment.bind(this));
+ this.createInputField();
+
+ new trackMouse(slider, this.updateSlider.bind(this), this.startMove.bind(this));
+ slider.addEventListener('click', function(e) {
+ this.startMove();
+ this.updateSlider(e);
+ }.bind(this));
+
+ sliders[topic] = this;
+ this.setValue(this.value);
+ };
+
+ Slider.prototype.createSetButton = function createSetButton(type, callback) {
+ var button = document.createElement('div');
+ button.className = 'ui-slider-button';
+ button.textContent = type;
+ button.addEventListener("click", callback);
+ this.node.appendChild(button);
+ };
+
+ Slider.prototype.createInputField = function createInputField() {
+ var input = document.createElement('input');
+ input.setAttribute('type', 'text');
+ this.node.appendChild(input);
+
+ input.addEventListener('click', function(e) {
+ this.select();
+ });
+
+ input.addEventListener('change', function(e) {
+ this.setValue(e.target.value | 0);
+ }.bind(this));
+
+ subscribe(this.topic, function(value) {
+ input.value = value + this.unit;
+ }.bind(this));
+ };
+
+ Slider.prototype.startMove = function startMove(e) {
+ this.sliderX = this.slider.getBoundingClientRect().left;
+ };
+
+ Slider.prototype.updateSlider = function updateSlider(e) {
+ var width = this.slider.clientWidth;
+ var pos = e.clientX - this.sliderX;
+ var delta = this.max - this.min;
+
+ if (pos &lt; 0) pos = 0;
+ if (pos &gt; width) pos = width;
+
+ var value = pos * delta / width | 0;
+ var precision = value % this.step;
+ value = value - precision + this.min;
+
+ if (precision &gt; this.step / 2)
+ value = value + this.step;
+
+ if (this.snap)
+ pos = (value - this.min) * width / delta;
+
+ this.pointer.style.left = pos + "px";
+ this.value = value;
+ notify.call(this);
+ };
+
+ Slider.prototype.increment = function increment() {
+ this.setValue(this.value + this.step);
+ };
+
+ Slider.prototype.decrement = function decrement() {
+ this.setValue(this.value - this.step);
+ };
+
+ Slider.prototype.setValue = function setValue(value) {
+ if (value &gt; this.max || value &lt; this.min)
+ return;
+
+ var delta = this.max - this.min;
+ var width = this.slider.clientWidth;
+ var pos = (value - this.min) * width / delta | 0;
+ this.value = value;
+ this.pointer.style.left = pos + "px";
+ notify.call(this);
+ };
+
+ var setValue = function setValue(topic, value) {
+ var slider = sliders[topic];
+ slider.setValue(value);
+ };
+
+ var subscribe = function subscribe(topic, callback) {
+ if (subscribers[topic] === undefined)
+ subscribers[topic] = [];
+ subscribers[topic].push(callback);
+ };
+
+ var unsubscribe = function unsubscribe(topic, callback) {
+ subscribers[topic].indexOf(callback);
+ subscribers[topic].splice(index, 1);
+ };
+
+ var notify = function notify() {
+ if (subscribers[this.topic] === undefined)
+ return;
+ for (var i = 0; i &lt; subscribers[this.topic].length; i++)
+ subscribers[this.topic][i](this.value);
+ };
+
+ var init = function init() {
+ var elem = document.querySelectorAll('.ui-slider');
+ var size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ new Slider(elem[i]);
+ };
+
+ return {
+ init : init,
+ setValue : setValue,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe
+ };
+
+})();
+
+window.addEventListener("load", function() {
+ LinearGradientTool.init();
+});
+
+window.addEventListener("load", function() {
+ LinearGradientTool.init();
+});
+
+var LinearGradientTool = (function LinearGradientTool() {
+ 'use strict';
+
+ var radian = 180 / Math.PI;
+ var inv_radian = Math.PI / 180;
+ var units = {'%': 1, 'px' : 0};
+
+ /*========== DOM Methods ==========*/
+
+ function getElemById(id) {
+ return document.getElementById(id);
+ }
+
+ function allowDropEvent(e) {
+ e.preventDefault();
+ }
+
+ function createClassElement(tag, className, parent) {
+ var elem = document.createElement(tag);
+ elem.className = className;
+ if (parent) parent.appendChild(elem);
+ return elem;
+ };
+
+ function trackMouse(elem, callback, startFunc, endFunc) {
+ startFunc = startFunc || function(e) {};
+ endFunc = endFunc || function(e) {};
+
+ elem.addEventListener('mousedown', function(e) {
+ e.preventDefault();
+ startFunc(e);
+
+ document.addEventListener('mousemove', callback);
+
+ document.addEventListener('mouseup', function up(e) {
+ document.removeEventListener('mousemove', callback);
+ document.removeEventListener('mouseup', up);
+ endFunc(e);
+ });
+ });
+
+ elem.addEventListener('click', function(e) {
+ e.stopPropagation();
+ });
+ }
+
+ var Color = UIColorPicker.Color;
+ var HSVColor = UIColorPicker.HSVColor;
+
+ var UIComponent = (function UIComponent() {
+
+ function makeResizable(elem, axis, callback, endFunc) {
+ var valueX = 0;
+ var valueY = 0;
+ var action = 0;
+ var callback = typeof callback === "function" ? callback : null;
+
+ endFunc = endFunc || function(e) {};
+
+ var resizeStart = function resizeStart(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ if (e.button !== 0)
+ return;
+
+ valueX = e.clientX - elem.clientWidth;
+ valueY = e.clientY - elem.clientHeight;
+
+ document.body.setAttribute('data-resize', axis);
+ document.addEventListener('mousemove', mouseMove);
+ document.addEventListener('mouseup', resizeEnd);
+ };
+
+ var mouseMove = function mouseMove(e) {
+ if (action &gt;= 0)
+ elem.style.width = e.clientX - valueX + 'px';
+ if (action &lt;= 0)
+ elem.style.height = e.clientY - valueY + 'px';
+ if (callback)
+ callback();
+ };
+
+ var resizeEnd = function resizeEnd(e) {
+ if (e.button !== 0)
+ return;
+
+ document.body.removeAttribute('data-resize', axis);
+ document.removeEventListener('mousemove', mouseMove);
+ document.removeEventListener('mouseup', resizeEnd);
+ endFunc();
+ };
+
+ var handle = document.createElement('div');
+ handle.className = 'resize-handle';
+
+ if (axis === 'width') action = 1;
+ else if (axis === 'height') action = -1;
+ else axis = 'both';
+
+ handle.className = 'resize-handle';
+ handle.setAttribute('data-resize', axis);
+ handle.addEventListener('mousedown', resizeStart);
+ elem.appendChild(handle);
+ };
+
+ return {
+ makeResizable : makeResizable
+ };
+ })();
+
+
+ /**
+ * Gradient Point
+ */
+ var GradientPoint = function GradientPoint(Axis) {
+ var point = document.createElement('div');
+
+ point.className = 'gradient-point';
+
+ this.position = 0;
+ this.node = point;
+ this.Axis = Axis;
+ this.color = new HSVColor(0, 0, 100);
+ this.CSScolor = this.color.getColor();
+ this.CSSposition = 0;
+ this.PrevPoint = null;
+ this.NextPoint = null;
+
+ this.Axis.num_points++;
+
+ point.addEventListener('click', this.activate.bind(this));
+ trackMouse(point, this.updatePositionM.bind(this), this.startMove.bind(this),
+ this.endMove.bind(this));
+
+ Axis.line.appendChild(point);
+ return this;
+ };
+
+ GradientPoint.prototype.deletePoint = function deletePoint() {
+ this.Axis.line.removeChild(this.node);
+ };
+
+ GradientPoint.prototype.activate = function activate() {
+ if (this.Axis.state === false)
+ return;
+
+ this.Axis.setActivePoint(this);
+ this.node.setAttribute('data-active', 'true');
+ UIColorPicker.setColor('picker', this.color);
+ InputSliderManager.setValue('point-position', this.CSSposition);
+ if (this.Axis.num_points &gt; 2)
+ AxesManager.setDeleteButtonState('active');
+ };
+
+ GradientPoint.prototype.deactivate = function deactivate() {
+ this.node.removeAttribute('data-active');
+ };
+
+ GradientPoint.prototype.startMove = function startMove(e) {
+ this.Axis.updateCenterPointPos();
+ this.node.setAttribute('data-active', 'true');
+ document.body.setAttribute('data-dragging', 'true');
+ };
+
+ GradientPoint.prototype.endMove = function endMove(e) {
+ this.node.removeAttribute('data-active', 'true');
+ document.body.removeAttribute('data-dragging');
+ };
+
+ GradientPoint.prototype.updatePositionM = function updatePositionM(e) {
+ var A = this.Axis;
+ var Qx = e.clientX - A.centerX;
+ var Qy = e.clientY - A.centerY;
+ this.position = (A.Px * Qx + A.Py * Qy) / A.Pmod + A.lsize;
+ this.updateCSSPosition();
+ this.Axis.reorderPoint(this);
+ this.Axis.updateGradient();
+ this.updateSlider();
+ };
+
+ GradientPoint.prototype.setPositionM = function setPositionM(posX, posY) {
+ var A = this.Axis;
+ var Qx = posX - A.centerX;
+ var Qy = posY - A.centerY;
+ this.position = (A.Px * Qx + A.Py * Qy) / A.Pmod + A.lsize;
+ this.updateCSSPosition();
+ this.Axis.reorderPoint(this);
+ this.Axis.updateGradient();
+ this.updateSlider();
+ };
+
+ GradientPoint.prototype.updateAbsolutePosition = function updateAbsolutePosition() {
+ if (this.Axis.unit ='%')
+ this.position = parseFloat(((this.CSSposition / 100) * (2 * this.Axis.lsize)).toFixed(1));;
+ };
+
+ GradientPoint.prototype.setPosition = function setPosition(pos) {
+ this.position = pos;
+ if (this.Axis.unit === '%')
+ this.position = parseFloat(((this.position / 100) * (2 * this.Axis.lsize)).toFixed(1));;
+ this.updateCSSPosition();
+ this.Axis.reorderPoint(this);
+ this.Axis.updateGradient();
+ };
+
+ GradientPoint.prototype.updateSlider = function updateSlider() {
+ if (this.Axis.ActivePoint === this &amp;&amp; this.Axis.state === true)
+ InputSliderManager.setValue('point-position', this.CSSposition, false);
+ };
+
+ GradientPoint.prototype.updateColor = function updateColor(color) {
+ this.color.copy(color);
+ this.CSScolor = color.getColor();
+ this.updateCSSvalue();
+ };
+
+ GradientPoint.prototype.updateCSSPosition = function updateCSSPosition() {
+ this.CSSposition = this.position | 0;
+ if (this.Axis.unit === '%')
+ this.CSSposition = parseFloat((100 * this.position / (2 * this.Axis.lsize)).toFixed(1));
+
+ this.node.style.left = this.CSSposition + this.Axis.unit;
+ this.updateCSSvalue();
+ };
+
+ GradientPoint.prototype.updateCSSvalue = function updateCSSvalue() {
+ this.CSSvalue = this.CSScolor + ' ' + this.CSSposition + this.Axis.unit;
+ };
+
+ GradientPoint.prototype.insertBefore = function insertBefore(point) {
+ this.NextPoint = point;
+ this.PrevPoint = point.PrevPoint;
+ point.PrevPoint = this;
+ if (this.PrevPoint)
+ this.PrevPoint.NextPoint = this;
+ };
+
+ GradientPoint.prototype.insertAfter = function insertAfter(point) {
+ this.NextPoint = point.NextPoint;
+ this.PrevPoint = point;
+ point.NextPoint = this;
+ if (this.NextPoint)
+ this.NextPoint.PrevPoint = this;
+ };
+
+
+ /**
+ * Gradient Axis
+ */
+ function GradientAxis(container, id) {
+ var axis = createClassElement('div', 'gradient-axis', null);
+ var line = createClassElement('div', 'gradient-line', axis);
+ var rotate_point = createClassElement('div', 'rotate-point', axis);
+
+ axis.setAttribute('axisID', id);
+
+ var svg = this.createSVGArrow(id);
+ rotate_point.appendChild(svg);
+
+ this.id = id;
+ this.axis = axis;
+ this.unit = '%';
+ this.line = line;
+ this.container = container;
+ this.lsize = container.clientWidth / 2;
+ this.FirstPoint = null;
+ this.ActivePoint = null;
+ this.gradient = '';
+ this.num_points = 0;
+
+ this.size = 0;
+ this.angle = 0;
+ this.state = false;
+ this.updateOnResize();
+
+ trackMouse(rotate_point, this.updateAxisAngle.bind(this),
+ this.startRotation.bind(this));
+
+ container.appendChild(axis);
+ line.addEventListener('click', this.placeGradientPoint.bind(this));
+ };
+
+
+ GradientAxis.prototype.createSVGArrow = function createSVGArrow(id) {
+ var xmlns = 'http://www.w3.org/2000/svg';
+ var svg = document.createElementNS(xmlns, 'svg');
+ var path = document.createElementNS(xmlns, 'path');
+
+ svg.setAttribute('class', 'gradient-arrow');
+
+ svg.setAttribute('width', '25');
+ svg.setAttribute('height', '25');
+
+ path.setAttribute('fill', '#CCC');
+ path.setAttribute('d', 'M 25,12.5 L 0,0 L 7.5,12.5 L 0,25');
+ svg.appendChild(path);
+
+ return svg;
+ };
+
+ GradientAxis.prototype.placeGradientPoint = function placeGradientPoint(e) {
+ this.updateCenterPointPos();
+ var point = new GradientPoint(this);
+ point.setPositionM(e.clientX, e.clientY);
+ point.activate();
+ this.attachPoint(point);
+ this.updateGradient();
+ };
+
+ GradientAxis.prototype.newGradientPoint = function newGradientPoint(pos) {
+ var point = new GradientPoint(this);
+ point.setPosition(pos);
+ point.activate();
+ this.attachPoint(point);
+ this.updateGradient();
+ };
+
+ GradientAxis.prototype.attachPoint = function attachPoint(point) {
+
+ // add the first point
+ if (this.FirstPoint === null) {
+ this.FirstPoint = point;
+ return;
+ }
+
+ // insert the point into the list
+ var p = this.FirstPoint;
+ while (p.NextPoint) {
+ if (point.CSSposition &lt; p.CSSposition) {
+ point.insertBefore(p);
+ if (point.PrevPoint === null)
+ this.FirstPoint = point;
+ return;
+ }
+ p = p.NextPoint;
+ };
+
+ // test the last point
+ if (point.CSSposition &lt; p.CSSposition)
+ point.insertBefore(p);
+ else
+ point.insertAfter(p);
+
+ if (point.PrevPoint === null)
+ this.FirstPoint = point;
+
+ return;
+ };
+
+ GradientAxis.prototype.detachPoint = function detachPoint(point) {
+ if (this.FirstPoint === point)
+ this.FirstPoint = point.NextPoint;
+ if (point.PrevPoint)
+ point.PrevPoint.NextPoint = point.NextPoint;
+ if (point.NextPoint)
+ point.NextPoint.PrevPoint = point.PrevPoint;
+ point.NextPoint = null;
+ point.PrevPoint = null;
+ };
+
+ GradientAxis.prototype.deleteActivePoint = function deleteActivePoint() {
+ // return if only 2 points left on the axis
+ if (this.num_points === 2)
+ return;
+
+ if (this.ActivePoint) {
+ this.ActivePoint.deletePoint();
+ this.detachPoint(this.ActivePoint);
+ this.updateGradient();
+ this.num_points--;
+ }
+ };
+
+ GradientAxis.prototype.reorderPoint = function reorderPoint(point) {
+ if (point.NextPoint &amp;&amp; point.NextPoint.CSSposition &gt; point.CSSposition &amp;&amp;
+ point.PrevPoint &amp;&amp; point.PrevPoint.CSSposition &lt; point.CSSposition)
+ return;
+ if (point.NextPoint === point.PrevPoint)
+ return;
+
+ this.detachPoint(point);
+ this.attachPoint(point);
+ };
+
+ GradientAxis.prototype.setActivePoint = function setActivePoint(point) {
+ if (this.ActivePoint)
+ this.ActivePoint.deactivate();
+ this.ActivePoint = point;
+ };
+
+ GradientAxis.prototype.activate = function activate() {
+ this.state = true;
+ this.axis.setAttribute('data-active', this.state);
+ InputSliderManager.setUnit('point-position', this.unit, false);
+ SliderManager.setValue('axis-rotation', this.angle | 0, false);
+ DropDownManager.setValue('axis-unit', units[this.unit], false);
+
+ if (this.ActivePoint)
+ this.ActivePoint.activate();
+ };
+
+ GradientAxis.prototype.deactivate = function deactivate() {
+ this.state = false;
+ this.axis.removeAttribute('data-active', this.state);
+ if (this.ActivePoint)
+ this.ActivePoint.deactivate();
+ };
+
+ GradientAxis.prototype.deleteAxis = function deleteAxis() {
+ this.deactivate();
+ this.container.removeChild(this.axis);
+ };
+
+ GradientAxis.prototype.updatePointColor = function updatePointColor(color) {
+ if (this.ActivePoint)
+ this.ActivePoint.updateColor(color);
+ this.updateGradient();
+ };
+
+ GradientAxis.prototype.updatePointPosition = function updatePointPosition(value) {
+ if (this.ActivePoint)
+ this.ActivePoint.setPosition(value);
+ };
+
+ GradientAxis.prototype.setUnit = function setUnit(unit) {
+ this.unit = unit;
+ this.updateAllPoints();
+ InputSliderManager.setUnit('point-position', unit, false);
+
+ if (this.ActivePoint)
+ this.ActivePoint.updateSlider();
+
+ this.updateGradient();
+ };
+
+ GradientAxis.prototype.updateAllPoints = function updateAllPoints() {
+ var p = this.FirstPoint;
+ while(p) {
+ p.updateCSSPosition();
+ p = p.NextPoint;
+ }
+ };
+
+ /* Axis events */
+ GradientAxis.prototype.startRotation = function startRotation(e) {
+ this.updateCenterPointPos();
+ this.updateAxisAngle(e);
+ };
+
+ GradientAxis.prototype.updateOnResize = function updateOnResize() {
+ this.updateContainer();
+ this.updateCenterPointPos();
+ this.setAxisAngle(this.angle);
+ };
+
+ GradientAxis.prototype.updateCenterPointPos = function updateCenterPointPos() {
+ var pos = this.container.getBoundingClientRect();
+ this.centerX = (pos.left + pos.right) / 2;
+ this.centerY = (pos.top + pos.bottom) / 2;
+ };
+
+ GradientAxis.prototype.updateContainer = function updateContainer() {
+ var W = this.container.clientWidth;
+ var H = this.container.clientHeight;
+
+ var max_size = Math.sqrt(W * W + H * H) + 50;
+
+ this.axis.style.width = max_size + 'px';
+ this.axis.style.left = (W - max_size)/2 - 1 + 'px';
+
+ this.mW = W / 2;
+ this.mH = H / 2;
+ };
+
+ GradientAxis.prototype.updateAxisAngle = function updateAxisAngle(e) {
+
+ var Px = e.clientX - this.centerX;
+ var Py = e.clientY - this.centerY;
+ var deg = -Math.atan2(Py, Px) * radian;
+ var Pmod = Math.sqrt(Px * Px + Py * Py);
+ this.lsize = (this.mW * Math.abs(Px) + this.mH * Math.abs(Py)) / Pmod;
+
+ if (this.state === true)
+ SliderManager.setValue('axis-rotation', deg | 0, false);
+
+ this.angle = deg;
+ this.updateCSS();
+ AxesManager.updateCSSGradient();
+
+ this.Px = Px;
+ this.Py = Py;
+ this.Pmod = Pmod;
+ };
+
+ GradientAxis.prototype.setAxisAngle = function setAxisAngle(deg) {
+ var rad = -deg * inv_radian;
+ var Px = Math.cos(rad);
+ var Py = Math.sin(rad);
+ this.lsize = this.mW * Math.abs(Px) + this.mH * Math.abs(Py);
+
+ this.angle = deg;
+ this.updateCSS();
+ AxesManager.updateCSSGradient();
+
+ this.Px = Px;
+ this.Py = Py;
+ this.Pmod = 1;
+ };
+
+ /* UI Methods - apply CSS */
+
+ GradientAxis.prototype.updateCSS = function updateCSS() {
+ this.line.style.width = 2 * this.lsize + 'px';
+ this.axis.style.transform = 'rotate('+ -this.angle +'deg)';
+ this.axis.style.webkitTransform = 'rotate('+ -this.angle +'deg)';
+ };
+
+ GradientAxis.prototype.updateGradient = function updateGradient() {
+ var p = this.FirstPoint;
+ if (p === null)
+ return;
+
+ this.gradient = p.CSSvalue;
+ p = p.NextPoint;
+ while(p) {
+ this.gradient += ', ' + p.CSSvalue;
+ p = p.NextPoint;
+ };
+ AxesManager.updateCSSGradient();
+ };
+
+ // this is the standard syntax
+ GradientAxis.prototype.getCSSGradient = function getCSSGradient() {
+ return 'linear-gradient('+ (-this.angle + 90 | 0) +'deg, ' + this.gradient + ')';
+ };
+
+ /**
+ * AxesManager
+ */
+ var AxesManager = (function AxesManager() {
+
+ var lg_axes = [];
+ var ActiveAxis = null;
+ var ActiveShortcut = null;
+ var axes_menu = null;
+ var gradient_container = null;
+ var add_axis_btn;
+ var delete_axis_btn;
+ var delete_point_btn;
+ var update_output;
+ var dragElem;
+
+ var createStartAxis = function createStartAxis(angle) {
+
+ if (ActiveAxis)
+ ActiveAxis.deactivate();
+
+ var axisID = getNextAxisID();
+ var axis = new GradientAxis(gradient_container, axisID);
+ var color = new HSVColor(210, 90, 90);
+ ActiveAxis = axis;
+
+ axis.activate();
+ axis.setAxisAngle(angle);
+ axis.newGradientPoint(10);
+ axis.updatePointColor(color);
+
+ color.setAlpha(0.5);
+ axis.newGradientPoint(50);
+ axis.updatePointColor(color);
+
+ color.setHue(275);
+ axis.newGradientPoint(50);
+ axis.updatePointColor(color);
+
+ color.setAlpha(1);
+ axis.newGradientPoint(90);
+ axis.updatePointColor(color);
+
+ UIColorPicker.setColor('picker', color);
+ lg_axes.push(axis);
+
+ axis.Shortcut = createAxisShortcut(axisID);
+ axis.activate();
+ };
+
+ var createAxis = function createAxis(angle) {
+
+ if (ActiveAxis)
+ ActiveAxis.deactivate();
+
+ var axisID = getNextAxisID();
+ var axis = new GradientAxis(gradient_container, axisID);
+ var color = new HSVColor(0, 0, 50);
+ ActiveAxis = axis;
+
+ axis.activate();
+ axis.setAxisAngle(angle);
+ axis.newGradientPoint(10);
+ axis.updatePointColor(color);
+
+ color.setValue(90);
+ axis.newGradientPoint(90);
+ axis.updatePointColor(color);
+
+ UIColorPicker.setColor('picker', color);
+ lg_axes.push(axis);
+
+ axis.Shortcut = createAxisShortcut(axisID);
+ axis.activate();
+ };
+
+ var createAxisShortcut = function createAxisShortcut(axisID) {
+ var axis = createClassElement('div', 'axis', axes_menu);
+
+ axis.setAttribute('axisID', axisID);
+ axis.setAttribute('draggable', 'true');
+ axis.style.left = (lg_axes.length - 1) * 60 + 'px';
+
+ axis.addEventListener('click', function() {
+ activateAxisShortcut(axis);
+ var axisID = this.getAttribute('axisID') | 0;
+ activateAxis(axisID);
+ });
+
+ axis.addEventListener('dragstart', function (e) {
+ dragElem = this;
+ e.dataTransfer.setData('axisID', this.getAttribute('axisID'));
+ });
+ axis.addEventListener('dragover', allowDropEvent);
+ axis.addEventListener('drop', function swap(e) {
+ if (dragElem === this)
+ return;
+
+ var from = getOrderID(e.dataTransfer.getData('axisID'));
+ var to = getOrderID(this.getAttribute('axisID'));
+
+ var swap = lg_axes[from];
+ lg_axes[from] = lg_axes[to];
+ lg_axes[to] = swap;
+
+ var left = dragElem.offsetLeft;
+ dragElem.style.left = this.offsetLeft + 'px';
+ this.style.left = left + 'px';
+
+ updateCSSGradient();
+ });
+
+ activateAxisShortcut(axis);
+ return axis;
+ };
+
+ var activateAxisShortcut = function activateAxisShortcut(node) {
+ if (ActiveShortcut)
+ ActiveShortcut.removeAttribute('data-state');
+ node.setAttribute('data-state', 'active');
+ ActiveShortcut = node;
+ };
+
+ var getNextAxisID = function getNextAxisID() {
+ var ids = [];
+ var idx = 0;
+ var len = lg_axes.length;
+
+ for (var i=0; i 1)
+ delete_axis_btn.removeAttribute('data-state');
+ };
+
+ /* Axis functions */
+
+ var updateAxisRotation = function updateAxisRotation(value) {
+ ActiveAxis.setAxisAngle(value);
+ };
+
+ var setAxisUnit = function setAxisUnit(obj) {
+ ActiveAxis.setUnit(obj.value);
+ };
+
+ var setAddAxisButton = function setAddAxisButton() {
+ add_axis_btn = getElemById('add-axis');
+ add_axis_btn.addEventListener('click', function() {
+ if (lg_axes.length === 4)
+ return;
+
+ createAxis(0);
+
+ if (lg_axes.length &gt; 1)
+ delete_axis_btn.removeAttribute('data-state');
+ if (lg_axes.length === 4)
+ this.setAttribute('data-state', 'disabled');
+ });
+ };
+
+ var setDeleteAxisButton = function setDeleteAxisButton() {
+ delete_axis_btn = getElemById('delete-axis');
+ delete_axis_btn.addEventListener('click', function () {
+ if (this.hasAttribute('data-state'))
+ return;
+ if (lg_axes.length === 1)
+ return;
+
+ axes_menu.removeChild(ActiveAxis.Shortcut);
+ ActiveAxis.deleteAxis();
+ lg_axes.splice(getOrderID(ActiveAxis.id), 1);
+
+ ActiveAxis = null;
+ updateCSSGradient();
+
+ var len = lg_axes.length;
+ for (var i=0; i</pre>
+</div>
+
+<p>{{Draft}}</p>
+
+<p>Dieses Werkzeug kann dazu verwendet werden, um benutzerdefinierte CSS3 {{cssxref("linear-gradient")}} Hintergründe zu erstellen.</p>
+
+<p>{{EmbedLiveSample('linear-gradient_generator', '100%', '1000')}}</p>