aboutsummaryrefslogtreecommitdiff
path: root/files/de/web/css/tools/linear-gradient_generator/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/de/web/css/tools/linear-gradient_generator/index.html')
-rw-r--r--files/de/web/css/tools/linear-gradient_generator/index.html3328
1 files changed, 3328 insertions, 0 deletions
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>