This tool lets you construct CSS box-shadow
effects, to add box shadow effects to your CSS objects.
<div id="container"> <div class="group section"> <div id="layer_manager"> <div class="group section"> <div class="button" data-type="add"> </div> <div class="button" data-type="move-up"> </div> <div class="button" data-type="move-down"> </div> </div> <div id="stack_container"></div> </div> <div id="preview_zone"> <div id="layer_menu" class="col span_12"> <div class="button" id="element" data-type="subject" data-title="element"> element </div> <div class="button" id="before" data-type="subject" data-title=":before"> :before <span class="delete" data-type="disable"></span> </div> <div class="button" id="after" data-type="subject" data-title=":after"> :after <span class="delete" data-type="disable"></span> </div> <div class="ui-checkbox" data-topic='before' data-label=":before"></div> <div class="ui-checkbox" data-topic='after' data-label=":after"></div> </div> <div id="preview"> <div id="obj-element"> <div class="content"> </div> <div id="obj-before"> </div> <div id="obj-after"> </div> </div> </div> </div> </div> <div id="controls" class="group section"> <div class="wrap-left"> <div class="colorpicker category"> <div class="title"> </div> <div id="colorpicker" class="group"> <div id="gradient" class="gradient"> <div id="gradient_picker"> </div> </div> <div id="hue" data-topic="hue" class="hue"> <div id="hue_selector"> </div> </div> <div class="info"> <div class="input" data-topic="hue" data-title='H:' data-action="HSV"></div> <div class="input" data-topic="saturation" data-title='S:' data-action="HSV"></div> <div class="input" data-topic="value" data-title='V:' data-action="HSV"></div> </div> <div class="alpha"> <div id="alpha" data-topic="alpha"> <div id="alpha_selector"> </div> </div> </div> <div class="info"> <div class="input" data-topic="r" data-title='R:' data-action="RGB"></div> <div class="input" data-topic="g" data-title='G:' data-action="RGB"></div> <div class="input" data-topic="b" data-title='B:' data-action="RGB"></div> </div> <div class="preview block"> <div id="output_color"> </div> </div> <div class="block info"> <div class="input" data-topic="a" data-title='alpha:' data-action="alpha"></div> <div class="input" data-topic="hexa" data-title='' data-action="hexa"></div> </div> </div> </div> </div> <div class="wrap-right"> <div id="shadow_properties" class="category"> <div class="title"> Shadow properties </div> <div class="group"> <div class="group property"> <div class="ui-slider-name"> inset </div> <div class="ui-checkbox" data-topic='inset'></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> Position x </div> <div class="ui-slider-btn-set" data-topic="posX" data-type="sub"></div> <div class="ui-slider" data-topic="posX" data-min="-500" data-max="500" data-step="1"> </div> <div class="ui-slider-btn-set" data-topic="posX" data-type="add"></div> <div class="ui-slider-input" data-topic="posX" data-unit="px"></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> Position y </div> <div class="ui-slider-btn-set" data-topic="posY" data-type="sub"></div> <div class="ui-slider" data-topic="posY" data-min="-500" data-max="500" data-step="1"> </div> <div class="ui-slider-btn-set" data-topic="posY" data-type="add"></div> <div class="ui-slider-input" data-topic="posY" data-unit="px"></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> Blur </div> <div class="ui-slider-btn-set" data-topic="blur" data-type="sub"></div> <div class="ui-slider" data-topic="blur" data-min="0" data-max="200" data-step="1"> </div> <div class="ui-slider-btn-set" data-topic="blur" data-type="add"></div> <div class="ui-slider-input" data-topic="blur" data-unit="px"></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> Spread </div> <div class="ui-slider-btn-set" data-topic="spread" data-type="sub"></div> <div class="ui-slider" data-topic="spread" data-min="-100" data-max="100" data-step="1" data-value="50"> </div> <div class="ui-slider-btn-set" data-topic="spread" data-type="add"></div> <div class="ui-slider-input" data-topic="spread" data-unit="px"></div> </div> </div> </div> <div id="element_properties" class="category"> <div class="title"> Class element properties </div> <div class="group"> <div class="group property"> <div class="ui-slider-name"> border </div> <div class="ui-checkbox" data-topic='border-state' data-state="true"></div> </div> <div id="z-index" class="slidergroup"> <div class="ui-slider-name"> z-index </div> <div class="ui-slider-btn-set" data-topic="z-index" data-type="sub"></div> <div class="ui-slider" data-topic="z-index" data-min="-10" data-max="10" data-step="1"></div> <div class="ui-slider-btn-set" data-topic="z-index" data-type="add"></div> <div class="ui-slider-input" data-topic="z-index"></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> top </div> <div class="ui-slider-btn-set" data-topic="top" data-type="sub"></div> <div class="ui-slider" data-topic="top" data-min="-500" data-max="500" data-step="1"> </div> <div class="ui-slider-btn-set" data-topic="top" data-type="add"></div> <div class="ui-slider-input" data-topic="top" data-unit="px"></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> left </div> <div class="ui-slider-btn-set" data-topic="left" data-type="sub"></div> <div class="ui-slider" data-topic="left" data-min="-300" data-max="700" data-step="1"> </div> <div class="ui-slider-btn-set" data-topic="left" data-type="add"></div> <div class="ui-slider-input" data-topic="left" data-unit="px"></div> </div> <div id="transform_rotate" class="slidergroup"> <div class="ui-slider-name"> Rotate </div> <div class="ui-slider-btn-set" data-topic="rotate" data-type="sub"></div> <div class="ui-slider" data-topic="rotate" data-min="-360" data-max="360" data-step="1" data-value="0"> </div> <div class="ui-slider-btn-set" data-topic="rotate" data-type="add"></div> <div class="ui-slider-input" data-topic="rotate" data-unit="deg"></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> Width </div> <div class="ui-slider-btn-set" data-topic="width" data-type="sub"></div> <div class="ui-slider" data-topic="width" data-min="0" data-max="1000" data-step="1" data-value="200"> </div> <div class="ui-slider-btn-set" data-topic="width" data-type="add"></div> <div class="ui-slider-input" data-topic="width" data-unit="px"></div> </div> <div class="slidergroup"> <div class="ui-slider-name"> Height </div> <div class="ui-slider-btn-set" data-topic="height" data-type="sub"></div> <div class="ui-slider" data-topic="height" data-min="0" data-max="400" data-step="1" data-value="200"> </div> <div class="ui-slider-btn-set" data-topic="height" data-type="add"></div> <div class="ui-slider-input" data-topic="height" data-unit="px"></div> </div> </div> </div> <div id="output" class="category"> <div id="menu" class="menu"></div> <div class="title"> CSS Code </div> <div class="group" style="border-top-left-radius: 0;"> <div class="output" data-topic="element" data-name="element" data-prop="width height background-color position=[relative] box-shadow"> </div> <div class="output" data-topic="before" data-name="element:before" data-prop="content=[""] position=[absolute] width height top left z-index background-color box-shadow transform -webkit-transform -ms-transform"> </div> <div class="output" data-topic="after" data-name="element:after" data-prop="content=[""] position=[absolute] width height top left z-index background-color box-shadow transform -webkit-transform -ms-transform"> </div> </div> </div> </div> </div> </div>
/* GRID OF TWELVE * ========================================================================== */ .span_12 { width: 100%; } .span_11 { width: 91.46%; } .span_10 { width: 83%; } .span_9 { width: 74.54%; } .span_8 { width: 66.08%; } .span_7 { width: 57.62%; } .span_6 { width: 49.16%; } .span_5 { width: 40.7%; } .span_4 { width: 32.24%; } .span_3 { width: 23.78%; } .span_2 { width: 15.32%; } .span_1 { width: 6.86%; } /* SECTIONS * ========================================================================== */ .section { clear: both; padding: 0px; margin: 0px; } /* GROUPING * ========================================================================== */ .group:before, .group:after { content: ""; display: table; } .group:after { clear:both; } .group { zoom: 1; /* For IE 6/7 (trigger hasLayout) */ } /* GRID COLUMN SETUP * ========================================================================== */ .col { display: block; float:left; margin: 1% 0 1% 1.6%; } .col:first-child { margin-left: 0; } /* all browsers except IE6 and lower */ /* * UI Slider */ .slidergroup { height: 20px; margin: 10px 0; font-family: "Segoe UI", Arial, Helvetica, sans-serif; -moz-user-select: none; user-select: none; } .slidergroup * { float: left; height: 100%; line-height: 100%; } /* Slider */ .ui-slider { height: 10px; width: 200px; margin: 4px 10px; display: block; border: 1px solid #999; border-radius: 3px; background: #EEE; } .ui-slider:hover { cursor: pointer; } .ui-slider-name { width: 90px; padding: 0 10px 0 0; text-align: right; text-transform: lowercase; } .ui-slider-pointer { width: 13px; height: 13px; background-color: #EEE; border: 1px solid #2C9FC9; border-radius: 3px; position: relative; top: -3px; left: 0%; } .ui-slider-btn-set { width: 25px; background-color: #2C9FC9; border-radius: 3px; color: #FFF; font-weight: bold; text-align: center; } .ui-slider-btn-set:hover { background-color: #379B4A; cursor: pointer; } .ui-slider-input > input { margin: 0 10px; padding: 0; width: 50px; text-align: center; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } /* * UI Button */ /* Checkbox */ .ui-checkbox { text-align: center; font-size: 16px; font-family: "Segoe UI", Arial, Helvetica, sans-serif; line-height: 1.5em; color: #FFF; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; } .ui-checkbox > input { display: none; } .ui-checkbox > label { font-size: 12px; padding: 0.333em 1.666em 0.5em; height: 1em; line-height: 1em; background-color: #888; background-image: url("https://mdn.mozillademos.org/files/5683/disabled.png"); background-position: center center; background-repeat: no-repeat; color: #FFF; border-radius: 3px; font-weight: bold; float: left; } .ui-checkbox .text { padding-left: 34px; background-position: center left 10px; } .ui-checkbox .left { padding-right: 34px; padding-left: 1.666em; background-position: center right 10px; } .ui-checkbox > label:hover { cursor: pointer; } .ui-checkbox > input:checked + label { background-image: url("https://mdn.mozillademos.org/files/5681/checked.png"); background-color: #379B4A; } /* * BOX SHADOW GENERATOR TOOL */ body { max-width: 1000px; height: 800px; margin: 20px auto 0; font-family: "Segoe UI", Arial, Helvetica, sans-serif; -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; } #container { width: 100%; padding: 2px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } /* container with shadows stacks */ #stack_container { height: 400px; overflow: hidden; position: relative; border: 1px solid #CCC; border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #stack_container .container { height: 100%; width: 100%; position: absolute; left: 100%; transition-property: left; transition-duration: 0.5s; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #stack_container .title { text-align: center; font-weight: bold; line-height: 2em; border-bottom: 1px solid #43A6E1; color: #666; } /* * Stack of Layers for shadow */ #layer_manager { width: 17%; background-color: #FEFEFE; margin: 0 1% 0 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; float: left; } #layer_manager .button { width: 30%; height: 25px; margin:0 0 10px; color: #333; background-color: #EEE; text-align: center; font-size: 0.75em; line-height: 1.5em; border: 1px solid #CCC; border-radius: 3px; display: block; background-position: center center; background-repeat: no-repeat; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; float: left; } #layer_manager .button:hover { background-color: #3380C4; border: 1px solid #3380C4; cursor: pointer; } #layer_manager [data-type='add'] { background-image: url("https://mdn.mozillademos.org/files/5685/add-black.png"); } #layer_manager [data-type='add']:hover { background-image: url("https://mdn.mozillademos.org/files/5687/add-white.png"); } #layer_manager [data-type='move-up'] { background-image: url("https://mdn.mozillademos.org/files/5697/up-black.png"); margin-left: 5%; margin-right: 5%; } #layer_manager [data-type='move-up']:hover { background-image: url("https://mdn.mozillademos.org/files/5709/up-white.png"); } #layer_manager [data-type='move-down'] { background-image: url("https://mdn.mozillademos.org/files/5693/down-black.png"); } #layer_manager [data-type='move-down']:hover { background-image: url("https://mdn.mozillademos.org/files/5695/down-white.png"); } /* shadows classes */ #layer_manager .node { width: 100%; margin: 5px 0; padding: 5px; text-align: center; background-color: #EEE; border: 1px solid #DDD; font-size: 0.75em; line-height: 1.5em; color: #333; border-radius: 3px; position: relative; display: block; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #layer_manager .node:hover { color: #FFF; background-color: #3380C4; cursor: pointer; } /* active element styling */ #layer_manager [data-active='layer'] { color: #FFF; border: none; background-color: #379B4A; } #layer_manager [data-active='subject'] { color: #FFF; background-color: #467FC9; } /* delete button */ #layer_manager .delete { width: 1.5em; height: 100%; float: right; border-radius: 3px; background-image: url("https://mdn.mozillademos.org/files/5689/delete-white.png"); background-position: center center; background-repeat: no-repeat; position: absolute; top: 0; right: 10px; display: none; } #layer_manager .delete:hover { background-image: url("https://mdn.mozillademos.org/files/5691/delete-yellow.png"); } #layer_manager .node:hover .delete { display: block; } #layer_manager .stack { padding: 0 5px; max-height: 90%; overflow: auto; overflow-x: hidden; } /* * Layer Menu */ #layer_menu { margin: 0 0 10px 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #layer_menu .button { width: 100px; margin: 0 5px 0 0; padding: 2.5px; color: #333; background-color: #EEE; border: 1px solid #CCC; border-radius: 3px; text-align: center; font-size: 0.75em; line-height: 1.5em; position: relative; display: block; float: left; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #layer_menu .button:hover { color: #FFF; background-color: #3380C4; border: 1px solid #3380C4; cursor: pointer; } #layer_menu .delete { width: 1.5em; height: 100%; float: right; border-radius: 3px; background-image: url("https://mdn.mozillademos.org/files/5689/delete-white.png"); background-position: center center; background-repeat: no-repeat; position: absolute; top: 0; right: 5px; display: none; } #layer_menu .delete:hover { background-image: url("https://mdn.mozillademos.org/files/5691/delete-yellow.png"); } #layer_menu .button:hover .delete { display: block; } /* * active element styling */ #layer_menu [data-active='subject'] { color: #FFF; background-color: #379B4A; border: 1px solid #379B4A; } /* Checkbox */ #layer_menu .ui-checkbox > label { height: 15px; line-height: 17px; font-weight: normal; width: 46px; margin: 0 5px 0 0; } #layer_menu .ui-checkbox > input:checked + label { display: none; } /******************************************************************************/ /******************************************************************************/ /* * Preview Area */ #preview_zone { width: 82%; float: left; } #preview { width: 100%; height: 400px; border: 1px solid #CCC; border-radius: 3px; text-align: center; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; cursor: move; float: left; } #preview .content { width: 100%; height: 100%; display: block; } #obj-element { width: 300px; height: 100px; border: 1px solid #CCC; background: #FFF; position: relative; } #obj-before { height: 100%; width: 100%; background: #999; border: 1px solid #CCC; text-align: left; display : block; position: absolute; z-index: -1; } #obj-after { height: 100%; width: 100%; background: #DDD; border: 1px solid #CCC; text-align: right; display : block; position: absolute; z-index: -1; } /******************************************************************************/ /******************************************************************************/ /** * Controls */ .wrap-left { float: left; overflow: hidden; } .wrap-right { float: right; overflow: hidden; } .wrap-left > * { float: left; } .wrap-right > * { float: right; } @media (min-width: 960px) { .wrap-left { width: 45%; } .wrap-right { width: 55%; } } @media (max-width: 959px) { .wrap-left { width: 30%; } .wrap-right { width: 70%; } } #controls { color: #444; margin: 10px 0 0 0; } #controls .category { width: 500px; margin: 0 auto 20px; padding: 0; } #controls .category .title { width: 100%; height: 1.5em; line-height: 1.5em; color: #AAA; text-align: right; } #controls .category > .group { border: 1px solid #CCC; border-radius: 3px; } /** * Color Picker */ @media (min-width: 960px) { #controls .colorpicker { width: 420px; } } @media (max-width: 959px) { #controls .colorpicker { width: 210px; } } #colorpicker { width: 100%; margin: 0 auto; } #colorpicker .gradient { width: 200px; height: 200px; margin: 5px; background: url("https://mdn.mozillademos.org/files/5707/picker_mask_200.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-color: #F00; float: left; } #colorpicker .hue { width: 200px; height: 30px; margin: 5px; background: url("https://mdn.mozillademos.org/files/5701/hue.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%); float: left; } #colorpicker .alpha { width: 200px; height: 30px; margin: 5px; border: 1px solid #CCC; float: left; background: url("https://mdn.mozillademos.org/files/5705/alpha.png"); -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #colorpicker #alpha { width: 100%; height: 100%; background: url("https://mdn.mozillademos.org/files/5703/alpha_mask.png"); background: -moz-linear-gradient(left, rgba(255, 0, 0, 0) 0%, rgba(255, 0, 0, 1) 100%); } #colorpicker #gradient_picker { width: 0.5em; height: 0.5em; border-radius: 0.4em; border: 2px solid #CCC; position: relative; top: 20%; left: 20%; } #colorpicker #hue_selector, #colorpicker #alpha_selector { width: 3px; height: 100%; border: 1px solid #777; background-color: #FFF; position: relative; top: -1px; left: 0%; } /* input HSV and RGB */ #colorpicker .info { width: 200px; margin: 5px; float: left; } #colorpicker .info * { float: left; } #colorpicker .info input { margin: 0; text-align: center; width: 30px; -moz-user-select: text; -webkit-user-select: text; -ms-user-select: text; } #colorpicker .info span { height: 20px; width: 30px; text-align: center; line-height: 20px; display: block; } /* Preview color */ #colorpicker .block { width: 95px; height: 54px; float: left; position: relative; } #colorpicker .preview { margin: 5px; border: 1px solid #CCC; background-image: url("https://mdn.mozillademos.org/files/5705/alpha.png"); -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #colorpicker .preview:before { height: 100%; width: 50%; left: 50%; content: ""; background: #FFF; position: absolute; z-index: 1; } #colorpicker .preview > * { width: 50%; height: 100%; } #colorpicker #output_color { width: 100%; height: 100%; position: absolute; z-index: 2; } #colorpicker .block .input { float: right; } #colorpicker [data-topic="a"] > span { width: 50px; } #colorpicker [data-topic="hexa"] { float: right; margin: 10px 0 0 0; } #colorpicker [data-topic="hexa"] > span { display: none; } #colorpicker [data-topic="hexa"] > input { width: 85px; padding: 2px 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } /* * UI Components */ /* Property */ .property { height: 20px; margin: 10px 0; } .property * { float: left; height: 100%; line-height: 100%; } /* Slider */ #controls .ui-slider-name { margin: 0 10px 0 0; } /* * Output code styling */ #output { position: relative; } #output .menu { max-width: 70%; height: 20px; position: absolute; top: 2px; } #output .button { width: 90px; height: 22px; margin: 0 5px 0 0; text-align: center; line-height: 20px; font-size: 14px; color: #FFF; background-color: #999; border-top-left-radius: 3px; border-top-right-radius: 3px; bottom: -5px; float:left; } #output .button:hover { color: #FFF; background-color: #666; cursor: pointer; } #output .menu [data-active="true"] { color: #777; background-color: #FFF; border: 1px solid #CCC; border-bottom: none; } #output .menu [data-topic="before"] { left: 100px; } #output .menu [data-topic="after"] { left: 200px; } #output .output { width: 480px; margin: 10px; padding: 10px; overflow: hidden; color: #555; font-size: 14px; border: 1px dashed #CCC; border-radius: 3px; display: none; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; -moz-user-select: text; -webkit-user-select: text; -ms-user-select: text; } #output .css-property { width: 100%; float: left; white-space: pre; } #output .name { width: 35%; float: left; } #output .value { width: 65%; float: left; }
'use strict'; /** * UI-SlidersManager */ var SliderManager = (function SliderManager() { var subscribers = {}; var sliders = []; var Slider = function(node) { 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'); var topic = node.getAttribute('data-topic'); this.min = min; this.max = max > 0 ? max : 100; this.step = step === 0 ? 1 : step; this.value = value <= max && value >= min ? value : (min + max) / 2 | 0; this.snap = snap === "true" ? true : false; this.topic = topic; this.node = node; var pointer = document.createElement('div'); pointer.className = 'ui-slider-pointer'; node.appendChild(pointer); this.pointer = pointer; setMouseTracking(node, updateSlider.bind(this)); sliders[topic] = this; setValue(topic, this.value); } var setButtonComponent = function setButtonComponent(node) { var type = node.getAttribute('data-type'); var topic = node.getAttribute('data-topic'); if (type === "sub") { node.textContent = '-'; node.addEventListener("click", function() { decrement(topic); }); } if (type === "add") { node.textContent = '+'; node.addEventListener("click", function() { increment(topic); }); } } var setInputComponent = function setInputComponent(node) { var topic = node.getAttribute('data-topic'); var unit_type = node.getAttribute('data-unit'); var input = document.createElement('input'); var unit = document.createElement('span'); unit.textContent = unit_type; input.setAttribute('type', 'text'); node.appendChild(input); node.appendChild(unit); input.addEventListener('click', function(e) { this.select(); }); input.addEventListener('change', function(e) { setValue(topic, e.target.value | 0); }); subscribe(topic, function(value) { node.children[0].value = value; }); } var increment = function increment(topic) { var slider = sliders[topic]; if (slider === null || slider === undefined) return; if (slider.value + slider.step <= slider.max) { slider.value += slider.step; setValue(slider.topic, slider.value) notify.call(slider); } }; var decrement = function decrement(topic) { var slider = sliders[topic]; if (slider === null || slider === undefined) return; if (slider.value - slider.step >= slider.min) { slider.value -= slider.step; setValue(topic, slider.value) notify.call(slider); } } // this = Slider object var updateSlider = function updateSlider(e) { var node = this.node; var pos = e.pageX - node.offsetLeft; var width = node.clientWidth; var delta = this.max - this.min; var offset = this.pointer.clientWidth + 4; // border width * 2 if (pos < 0) pos = 0; if (pos > width) pos = width; var value = pos * delta / width | 0; var precision = value % this.step; value = value - precision + this.min; if (precision > this.step / 2) value = value + this.step; if (this.snap) pos = (value - this.min) * width / delta; this.pointer.style.left = pos - offset/2 + "px"; this.value = value; node.setAttribute('data-value', value); notify.call(this); } var setValue = function setValue(topic, value) { var slider = sliders[topic]; if (value > slider.max || value < slider.min) return; var delta = slider.max - slider.min; var width = slider.node.clientWidth; var offset = slider.pointer.clientWidth; var pos = (value - slider.min) * width / delta; slider.value = value; slider.pointer.style.left = pos - offset / 2 + "px"; slider.node.setAttribute('data-value', value); notify.call(slider); } 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); }); } 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 in subscribers[this.topic]) { subscribers[this.topic][i](this.value); } } var init = function init() { var elem, size; elem = document.querySelectorAll('.ui-slider-btn-set'); size = elem.length; for (var i = 0; i < size; i++) setButtonComponent(elem[i]); elem = document.querySelectorAll('.ui-slider-input'); size = elem.length; for (var i = 0; i < size; i++) setInputComponent(elem[i]); elem = document.querySelectorAll('.ui-slider'); size = elem.length; for (var i = 0; i < size; i++) new Slider(elem[i]); } return { init : init, setValue : setValue, subscribe : subscribe, unsubscribe : unsubscribe } })(); /** * UI-ButtonManager */ var ButtonManager = (function CheckBoxManager() { var subscribers = []; var buttons = []; var CheckBox = function CheckBox(node) { var topic = node.getAttribute('data-topic'); var state = node.getAttribute('data-state'); var name = node.getAttribute('data-label'); var align = node.getAttribute('data-text-on'); state = (state === "true"); var checkbox = document.createElement("input"); var label = document.createElement("label"); var id = 'checkbox-' + topic; checkbox.id = id; checkbox.setAttribute('type', 'checkbox'); checkbox.checked = state; label.setAttribute('for', id); if (name) { label.className = 'text'; if (align) label.className += ' ' + align; label.textContent = name; } node.appendChild(checkbox); node.appendChild(label); this.node = node; this.topic = topic; this.checkbox = checkbox; checkbox.addEventListener('change', function(e) { notify.call(this); }.bind(this)); buttons[topic] = this; } var getNode = function getNode(topic) { return buttons[topic].node; } var setValue = function setValue(topic, value) { try { buttons[topic].checkbox.checked = value; notify.call(buttons[topic]); } catch(error) { console.log(error, topic, 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 < subscribers[this.topic].length; i++) subscribers[this.topic][i](this.checkbox.checked); } var init = function init() { var elem = document.querySelectorAll('.ui-checkbox'); var size = elem.length; for (var i = 0; i < size; i++) new CheckBox(elem[i]); } return { init : init, setValue : setValue, subscribe : subscribe, unsubscribe : unsubscribe } })(); window.addEventListener("load", function(){ BoxShadow.init(); }); var BoxShadow = (function BoxShadow() { function getElemById(id) { return document.getElementById(id); } /** * RGBA Color class */ function Color() { this.r = 0; this.g = 0; this.b = 0; this.a = 1; this.hue = 0; this.saturation = 0; this.value = 0; } Color.prototype.copy = function copy(obj) { if(obj instanceof Color !== true) { console.log("Typeof instance 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; } Color.prototype.setRGBA = function setRGBA(red, green, blue, alpha) { if (red != undefined) this.r = red | 0; if (green != undefined) this.g = green | 0; if (blue != undefined) this.b = blue | 0; if (alpha != undefined) this.a = alpha | 0; } /** * HSV/HSB (hue, saturation, value / brightness) * @param hue 0-360 * @param saturation 0-100 * @param value 0-100 */ Color.prototype.setHSV = function setHSV(hue, saturation, value) { this.hue = hue; this.saturation = saturation; this.value = value; this.updateRGB(); } Color.prototype.updateRGB = function updateRGB() { 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; X = (X + m) * precision; m = m * precision; if (H >= 0 && H < 1) { this.setRGBA(C, X, m); return; } if (H >= 1 && H < 2) { this.setRGBA(X, C, m); return; } if (H >= 2 && H < 3) { this.setRGBA(m, C, X); return; } if (H >= 3 && H < 4) { this.setRGBA(m, X, C); return; } if (H >= 4 && H < 5) { this.setRGBA(X, m, C); return; } if (H >= 5 && H < 6) { this.setRGBA(C, m, X); return; } } Color.prototype.updateHSV = function updateHSV() { 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 < 0) this.hue += 360; this.saturation = (saturation * 100) | 0; this.value = (cmax * 100) | 0; } 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; } 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 < 16) r = '0' + r; if (this.g < 16) g = '0' + g; if (this.b < 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 = ''; if (this.a !== 1) { a = 'a'; v = ', ' + this.a; } var value = "rgb" + a + rgb + v + ")"; return value; } Color.prototype.getColor = function getColor() { if (this.a | 0 === 1) return this.getHexa(); return this.getRGBA(); } /** * Shadow Object */ function Shadow() { this.inset = false; this.posX = 5; this.posY = -5; this.blur = 5; this.spread = 0; this.color = new Color(); var hue = (Math.random() * 360) | 0; var saturation = (Math.random() * 75) | 0; var value = (Math.random() * 50 + 50) | 0; this.color.setHSV(hue, saturation, value, 1); } Shadow.prototype.computeCSS = function computeCSS() { var value = ""; if (this.inset === true) value += "inset "; value += this.posX + "px "; value += this.posY + "px "; value += this.blur + "px "; value += this.spread + "px "; value += this.color.getColor(); return value; } Shadow.prototype.toggleInset = function toggleInset(value) { if (value !== undefined || typeof value === "boolean") this.inset = value; else this.inset = this.inset === true ? false : true; } Shadow.prototype.copy = function copy(obj) { if(obj instanceof Shadow !== true) { console.log("Typeof instance not Shadow"); return; } this.inset = obj.inset; this.posX = obj.posX; this.posY = obj.posY; this.blur = obj.blur; this.spread = obj.spread; this.color.copy(obj.color); } /** * Color Picker */ var ColoPicker = (function ColoPicker() { var colorpicker; var hue_area; var gradient_area; var alpha_area; var gradient_picker; var hue_selector; var alpha_selector; var pick_object; var info_rgb; var info_hsv; var info_hexa; var output_color; var color = new Color(); var subscribers = []; var updateColor = function updateColor(e) { var x = e.pageX - gradient_area.offsetLeft; var y = e.pageY - gradient_area.offsetTop; // width and height should be the same var size = gradient_area.clientWidth; if (x > size) x = size; if (y > size) y = size; if (x < 0) x = 0; if (y < 0) y = 0; var value = 100 - (y * 100 / size) | 0; var saturation = x * 100 / size | 0; color.setHSV(color.hue, saturation, value); // should update just // color pointer location updateUI(); notify("color", color); } var updateHue = function updateHue(e) { var x = e.pageX - hue_area.offsetLeft; var width = hue_area.clientWidth; if (x < 0) x = 0; if (x > width) x = width; var hue = ((360 * x) / width) | 0; if (hue === 360) hue = 359; color.setHSV(hue, color.saturation, color.value); // should update just // hue pointer location // picker area background // alpha area background updateUI(); notify("color", color); } var updateAlpha = function updateAlpha(e) { var x = e.pageX - alpha_area.offsetLeft; var width = alpha_area.clientWidth; if (x < 0) x = 0; if (x > width) x = width; color.a = (x / width).toFixed(2); // should update just // alpha pointer location updateUI(); notify("color", color); } var setHueGfx = function setHueGfx(hue) { var sat = color.saturation; var val = color.value; var alpha = color.a; color.setHSV(hue, 100, 100); gradient_area.style.backgroundColor = color.getHexa(); color.a = 0; var start = color.getRGBA(); color.a = 1; var end = color.getRGBA(); color.a = alpha; var gradient = '-moz-linear-gradient(left, ' + start + '0%, ' + end + ' 100%)'; alpha_area.style.background = gradient; } var updateUI = function updateUI() { var x, y; // coordinates var size; // size of the area var offset; // pointer graphic selector offset // Set color pointer location size = gradient_area.clientWidth; offset = gradient_picker.clientWidth / 2 + 2; x = (color.saturation * size / 100) | 0; y = size - (color.value * size / 100) | 0; gradient_picker.style.left = x - offset + "px"; gradient_picker.style.top = y - offset + "px"; // Set hue pointer location size = hue_area.clientWidth; offset = hue_selector.clientWidth/2; x = (color.hue * size / 360 ) | 0; hue_selector.style.left = x - offset + "px"; // Set alpha pointer location size = alpha_area.clientWidth; offset = alpha_selector.clientWidth/2; x = (color.a * size) | 0; alpha_selector.style.left = x - offset + "px"; // Set picker area background var nc = new Color(); nc.copy(color); if (nc.hue === 360) nc.hue = 0; nc.setHSV(nc.hue, 100, 100); gradient_area.style.backgroundColor = nc.getHexa(); // Set alpha area background nc.copy(color); nc.a = 0; var start = nc.getRGBA(); nc.a = 1; var end = nc.getRGBA(); var gradient = '-moz-linear-gradient(left, ' + start + '0%, ' + end + ' 100%)'; alpha_area.style.background = gradient; // Update color info notify("color", color); notify("hue", color.hue); notify("saturation", color.saturation); notify("value", color.value); notify("r", color.r); notify("g", color.g); notify("b", color.b); notify("a", color.a); notify("hexa", color.getHexa()); output_color.style.backgroundColor = color.getRGBA(); } var setInputComponent = function setInputComponent(node) { var topic = node.getAttribute('data-topic'); var title = node.getAttribute('data-title'); var action = node.getAttribute('data-action'); title = title === null ? '' : title; var input = document.createElement('input'); var info = document.createElement('span'); info.textContent = title; input.setAttribute('type', 'text'); input.setAttribute('data-action', 'set-' + action + '-' + topic); node.appendChild(info); node.appendChild(input); input.addEventListener('click', function(e) { this.select(); }); input.addEventListener('change', function(e) { if (action === 'HSV') inputChangeHSV(topic); if (action === 'RGB') inputChangeRGB(topic); if (action === 'alpha') inputChangeAlpha(topic); if (action === 'hexa') inputChangeHexa(topic); }); subscribe(topic, function(value) { node.children[1].value = value; }); } var inputChangeHSV = function actionHSV(topic) { var selector = "[data-action='set-HSV-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector); var value = parseInt(node.value); if (typeof value === 'number' && isNaN(value) === false && value >= 0 && value < 360) color[topic] = value; color.updateRGB(); updateUI(); } var inputChangeRGB = function inputChangeRGB(topic) { var selector = "[data-action='set-RGB-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector); var value = parseInt(node.value); if (typeof value === 'number' && isNaN(value) === false && value >= 0 && value <= 255) color[topic] = value; color.updateHSV(); updateUI(); } var inputChangeAlpha = function inputChangeAlpha(topic) { var selector = "[data-action='set-alpha-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector); var value = parseFloat(node.value); if (typeof value === 'number' && isNaN(value) === false && value >= 0 && value <= 1) color.a = value.toFixed(2); updateUI(); } var inputChangeHexa = function inputChangeHexa(topic) { var selector = "[data-action='set-hexa-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector); var value = node.value; color.setHexa(value); color.updateHSV(); updateUI(); } 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); }); } /* * Observer */ var setColor = function setColor(obj) { if(obj instanceof Color !== true) { console.log("Typeof instance not Color"); return; } color.copy(obj); updateUI(); } 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) { for (var i in subscribers[topic]) subscribers[topic][i](value); } var init = function init() { colorpicker = getElemById("colorpicker"); hue_area = getElemById("hue"); gradient_area = getElemById("gradient"); alpha_area = getElemById("alpha"); gradient_picker = getElemById("gradient_picker"); hue_selector = getElemById("hue_selector"); alpha_selector = getElemById("alpha_selector"); output_color = getElemById("output_color"); var elem = document.querySelectorAll('#colorpicker .input'); var size = elem.length; for (var i = 0; i < size; i++) setInputComponent(elem[i]); setMouseTracking(gradient_area, updateColor); setMouseTracking(hue_area, updateHue); setMouseTracking(alpha_area, updateAlpha); } return { init : init, setColor : setColor, subscribe : subscribe, unsubscribe : unsubscribe } })(); /** * Shadow dragging */ var PreviewMouseTracking = (function Drag() { var active = false; var lastX = 0; var lastY = 0; var subscribers = []; var init = function init(id) { var elem = getElemById(id); elem.addEventListener('mousedown', dragStart, false); document.addEventListener('mouseup', dragEnd, false); } var dragStart = function dragStart(e) { if (e.button !== 0) return; active = true; lastX = e.clientX; lastY = e.clientY; document.addEventListener('mousemove', mouseDrag, false); } var dragEnd = function dragEnd(e) { if (e.button !== 0) return; if (active === true) { active = false; document.removeEventListener('mousemove', mouseDrag, false); } } var mouseDrag = function mouseDrag(e) { notify(e.clientX - lastX, e.clientY - lastY); lastX = e.clientX; lastY = e.clientY; } var subscribe = function subscribe(callback) { subscribers.push(callback); } var unsubscribe = function unsubscribe(callback) { var index = subscribers.indexOf(callback); subscribers.splice(index, 1); } var notify = function notify(deltaX, deltaY) { for (var i in subscribers) subscribers[i](deltaX, deltaY); } return { init : init, subscribe : subscribe, unsubscribe : unsubscribe } })(); /* * Element Class */ var CssClass = function CssClass(id) { this.left = 0; this.top = 0; this.rotate = 0; this.width = 300; this.height = 100; this.display = true; this.border = true; this.zIndex = -1; this.bgcolor = new Color(); this.id = id; this.node = getElemById('obj-' + id); this.object = getElemById(id); this.shadowID = null; this.shadows = [] this.render = []; this.init(); } CssClass.prototype.init = function init() { this.left = ((this.node.parentNode.clientWidth - this.node.clientWidth) / 2) | 0; this.top = ((this.node.parentNode.clientHeight - this.node.clientHeight) / 2) | 0; this.setTop(this.top); this.setLeft(this.left); this.setHeight(this.height); this.setWidth(this.width); this.bgcolor.setHSV(0, 0, 100); this.updateBgColor(this.bgcolor); } CssClass.prototype.updatePos = function updatePos(deltaX, deltaY) { this.left += deltaX; this.top += deltaY; this.node.style.top = this.top + "px"; this.node.style.left = this.left + "px"; SliderManager.setValue("left", this.left); SliderManager.setValue("top", this.top); } CssClass.prototype.setLeft = function setLeft(value) { this.left = value; this.node.style.left = this.left + "px"; OutputManager.updateProperty(this.id, 'left', this.left + 'px'); } CssClass.prototype.setTop = function setTop(value) { this.top = value; this.node.style.top = this.top + 'px'; OutputManager.updateProperty(this.id, 'top', this.top + 'px'); } CssClass.prototype.setWidth = function setWidth(value) { this.width = value; this.node.style.width = this.width + 'px'; OutputManager.updateProperty(this.id, 'width', this.width + 'px'); } CssClass.prototype.setHeight = function setHeight(value) { this.height = value; this.node.style.height = this.height + 'px'; OutputManager.updateProperty(this.id, 'height', this.height + 'px'); } // Browser support CssClass.prototype.setRotate = function setRotate(value) { var cssvalue = 'rotate(' + value +'deg)'; this.node.style.transform = cssvalue; this.node.style.webkitTransform = cssvalue; this.node.style.msTransform = cssvalue; if (value !== 0) { if (this.rotate === 0) { OutputManager.toggleProperty(this.id, 'transform', true); OutputManager.toggleProperty(this.id, '-webkit-transform', true); OutputManager.toggleProperty(this.id, '-ms-transform', true); } } else { OutputManager.toggleProperty(this.id, 'transform', false); OutputManager.toggleProperty(this.id, '-webkit-transform', false); OutputManager.toggleProperty(this.id, '-ms-transform', false); } OutputManager.updateProperty(this.id, 'transform', cssvalue); OutputManager.updateProperty(this.id, '-webkit-transform', cssvalue); OutputManager.updateProperty(this.id, '-ms-transform', cssvalue); this.rotate = value; } CssClass.prototype.setzIndex = function setzIndex(value) { this.node.style.zIndex = value; OutputManager.updateProperty(this.id, 'z-index', value); this.zIndex = value; } CssClass.prototype.toggleDisplay = function toggleDisplay(value) { if (typeof value !== "boolean" || this.display === value) return; this.display = value; var display = this.display === true ? "block" : "none"; this.node.style.display = display; this.object.style.display = display; } CssClass.prototype.toggleBorder = function toggleBorder(value) { if (typeof value !== "boolean" || this.border === value) return; this.border = value; var border = this.border === true ? "1px solid #CCC" : "none"; this.node.style.border = border; } CssClass.prototype.updateBgColor = function updateBgColor(color) { this.bgcolor.copy(color); this.node.style.backgroundColor = color.getColor(); OutputManager.updateProperty(this.id, 'background-color', color.getColor()); } CssClass.prototype.updateShadows = function updateShadows() { if (this.render.length === 0) OutputManager.toggleProperty(this.id, 'box-shadow', false); if (this.render.length === 1) OutputManager.toggleProperty(this.id, 'box-shadow', true); this.node.style.boxShadow = this.render.join(", "); OutputManager.updateProperty(this.id, 'box-shadow', this.render.join(", \n")); } /** * Tool Manager */ var Tool = (function Tool() { var preview; var classes = []; var active = null; var animate = false; /* * Toll actions */ var addCssClass = function addCssClass(id) { classes[id] = new CssClass(id); } var setActiveClass = function setActiveClass(id) { active = classes[id]; active.shadowID = null; ColoPicker.setColor(classes[id].bgcolor); SliderManager.setValue("top", active.top); SliderManager.setValue("left", active.left); SliderManager.setValue("rotate", active.rotate); SliderManager.setValue("z-index", active.zIndex); SliderManager.setValue("width", active.width); SliderManager.setValue("height", active.height); ButtonManager.setValue("border-state", active.border); active.updateShadows(); } var disableClass = function disableClass(topic) { classes[topic].toggleDisplay(false); ButtonManager.setValue(topic, false); } var addShadow = function addShadow(position) { if (animate === true) return -1; active.shadows.splice(position, 0, new Shadow()); active.render.splice(position, 0, null); } var swapShadow = function swapShadow(id1, id2) { var x = active.shadows[id1]; active.shadows[id1] = active.shadows[id2]; active.shadows[id2] = x; updateShadowCSS(id1); updateShadowCSS(id2); } var deleteShadow = function deleteShadow(position) { active.shadows.splice(position, 1); active.render.splice(position, 1); active.updateShadows(); } var setActiveShadow = function setActiveShadow(id, glow) { active.shadowID = id; ColoPicker.setColor(active.shadows[id].color); ButtonManager.setValue("inset", active.shadows[id].inset); SliderManager.setValue("blur", active.shadows[id].blur); SliderManager.setValue("spread", active.shadows[id].spread); SliderManager.setValue("posX", active.shadows[id].posX); SliderManager.setValue("posY", active.shadows[id].posY); if (glow === true) addGlowEffect(id); } var addGlowEffect = function addGlowEffect(id) { if (animate === true) return; animate = true; var store = new Shadow(); var shadow = active.shadows[id]; store.copy(shadow); shadow.color.setRGBA(40, 125, 200, 1); shadow.blur = 10; shadow.spread = 10; active.node.style.transition = "box-shadow 0.2s"; updateShadowCSS(id); setTimeout(function() { shadow.copy(store); updateShadowCSS(id); setTimeout(function() { active.node.style.removeProperty("transition"); animate = false; }, 100); }, 200); } var updateActivePos = function updateActivePos(deltaX, deltaY) { if (active.shadowID === null) active.updatePos(deltaX, deltaY); else updateShadowPos(deltaX, deltaY); } /* * Shadow properties */ var updateShadowCSS = function updateShadowCSS(id) { active.render[id] = active.shadows[id].computeCSS(); active.updateShadows(); } var toggleShadowInset = function toggleShadowInset(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].toggleInset(value); updateShadowCSS(active.shadowID); } var updateShadowPos = function updateShadowPos(deltaX, deltaY) { var shadow = active.shadows[active.shadowID]; shadow.posX += deltaX; shadow.posY += deltaY; SliderManager.setValue("posX", shadow.posX); SliderManager.setValue("posY", shadow.posY); updateShadowCSS(active.shadowID); } var setShadowPosX = function setShadowPosX(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].posX = value; updateShadowCSS(active.shadowID); } var setShadowPosY = function setShadowPosY(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].posY = value; updateShadowCSS(active.shadowID); } var setShadowBlur = function setShadowBlur(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].blur = value; updateShadowCSS(active.shadowID); } var setShadowSpread = function setShadowSpread(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].spread = value; updateShadowCSS(active.shadowID); } var updateShadowColor = function updateShadowColor(color) { active.shadows[active.shadowID].color.copy(color); updateShadowCSS(active.shadowID); } /* * Element Properties */ var updateColor = function updateColor(color) { if (active.shadowID === null) active.updateBgColor(color); else updateShadowColor(color); } var init = function init() { preview = getElemById("preview"); ColoPicker.subscribe("color", updateColor); PreviewMouseTracking.subscribe(updateActivePos); // Affects shadows ButtonManager.subscribe("inset", toggleShadowInset); SliderManager.subscribe("posX", setShadowPosX); SliderManager.subscribe("posY", setShadowPosY); SliderManager.subscribe("blur", setShadowBlur); SliderManager.subscribe("spread", setShadowSpread); // Affects element SliderManager.subscribe("top", function(value){ active.setTop(value); }); SliderManager.subscribe("left", function(value){ active.setLeft(value); }); SliderManager.subscribe("rotate", function(value) { if (active == classes["element"]) return; active.setRotate(value); }); SliderManager.subscribe("z-index", function(value) { if (active == classes["element"]) return; active.setzIndex(value); }); SliderManager.subscribe("width", function(value) { active.setWidth(value) }); SliderManager.subscribe("height", function(value) { active.setHeight(value) }); // Actions classes['before'].top = -30; classes['before'].left = -30; classes['after'].top = 30; classes['after'].left = 30; classes['before'].toggleDisplay(false); classes['after'].toggleDisplay(false); ButtonManager.setValue('before', false); ButtonManager.setValue('after', false); ButtonManager.subscribe("before", classes['before'].toggleDisplay.bind(classes['before'])); ButtonManager.subscribe("after", classes['after'].toggleDisplay.bind(classes['after'])); ButtonManager.subscribe("border-state", function(value) { active.toggleBorder(value); }); } return { init : init, addShadow : addShadow, swapShadow : swapShadow, addCssClass : addCssClass, disableClass : disableClass, deleteShadow : deleteShadow, setActiveClass : setActiveClass, setActiveShadow : setActiveShadow } })(); /** * Layer Manager */ var LayerManager = (function LayerManager() { var stacks = []; var active = { node : null, stack : null } var elements = {}; var mouseEvents = function mouseEvents(e) { var node = e.target; var type = node.getAttribute('data-type'); if (type === 'subject') setActiveStack(stacks[node.id]); if (type === 'disable') { Tool.disableClass(node.parentNode.id); setActiveStack(stacks['element']); } if (type === 'add') active.stack.addLayer(); if (type === 'layer') active.stack.setActiveLayer(node); if (type === 'delete') active.stack.deleteLayer(node.parentNode); if (type === 'move-up') active.stack.moveLayer(1); if (type === 'move-down') active.stack.moveLayer(-1); } var setActiveStack = function setActiveStack(stackObj) { active.stack.hide(); active.stack = stackObj; active.stack.show(); } /* * Stack object */ var Stack = function Stack(subject) { var S = document.createElement('div'); var title = document.createElement('div'); var stack = document.createElement('div'); S.className = 'container'; stack.className = 'stack'; title.className = 'title'; title.textContent = subject.getAttribute('data-title'); S.appendChild(title); S.appendChild(stack); this.id = subject.id; this.container = S; this.stack = stack; this.subject = subject; this.order = []; this.uid = 0; this.count = 0; this.layer = null; this.layerID = 0; } Stack.prototype.addLayer = function addLayer() { if (Tool.addShadow(this.layerID) == -1) return; var uid = this.getUID(); var layer = this.createLayer(uid); if (this.layer === null && this.stack.children.length >= 1) this.layer = this.stack.children[0]; this.stack.insertBefore(layer, this.layer); this.order.splice(this.layerID, 0, uid); this.count++; this.setActiveLayer(layer); } Stack.prototype.createLayer = function createLayer(uid) { var layer = document.createElement('div'); var del = document.createElement('span'); layer.className = 'node'; layer.setAttribute('data-shid', uid); layer.setAttribute('data-type', 'layer'); layer.textContent = 'shadow ' + uid; del.className = 'delete'; del.setAttribute('data-type', 'delete'); layer.appendChild(del); return layer; } Stack.prototype.getUID = function getUID() { return this.uid++; } // SOLVE IE BUG Stack.prototype.moveLayer = function moveLayer(direction) { if (this.count <= 1 || this.layer === null) return; if (direction === -1 && this.layerID === (this.count - 1) ) return; if (direction === 1 && this.layerID === 0 ) return; if (direction === -1) { var before = null; Tool.swapShadow(this.layerID, this.layerID + 1); this.swapOrder(this.layerID, this.layerID + 1); this.layerID += 1; if (this.layerID + 1 !== this.count) before = this.stack.children[this.layerID + 1]; this.stack.insertBefore(this.layer, before); Tool.setActiveShadow(this.layerID, false); } if (direction === 1) { Tool.swapShadow(this.layerID, this.layerID - 1); this.swapOrder(this.layerID, this.layerID - 1); this.layerID -= 1; this.stack.insertBefore(this.layer, this.stack.children[this.layerID]); Tool.setActiveShadow(this.layerID, false); } } Stack.prototype.swapOrder = function swapOrder(pos1, pos2) { var x = this.order[pos1]; this.order[pos1] = this.order[pos2]; this.order[pos2] = x; } Stack.prototype.deleteLayer = function deleteLayer(node) { var shadowID = node.getAttribute('data-shid') | 0; var index = this.order.indexOf(shadowID); this.stack.removeChild(this.stack.children[index]); this.order.splice(index, 1); this.count--; Tool.deleteShadow(index); if (index > this.layerID) return; if (index == this.layerID) { if (this.count >= 1) { this.layerID = 0; this.setActiveLayer(this.stack.children[0], true); } else { this.layer = null; this.show(); } } if (index < this.layerID) { this.layerID--; Tool.setActiveShadow(this.layerID, true); } } Stack.prototype.setActiveLayer = function setActiveLayer(node) { elements.shadow_properties.style.display = 'block'; elements.element_properties.style.display = 'none'; if (this.layer) this.layer.removeAttribute('data-active'); this.layer = node; this.layer.setAttribute('data-active', 'layer'); var shadowID = node.getAttribute('data-shid') | 0; this.layerID = this.order.indexOf(shadowID); Tool.setActiveShadow(this.layerID, true); } Stack.prototype.unsetActiveLayer = function unsetActiveLayer() { if (this.layer) this.layer.removeAttribute('data-active'); this.layer = null; this.layerID = 0; } Stack.prototype.hide = function hide() { this.unsetActiveLayer(); this.subject.removeAttribute('data-active'); var style = this.container.style; style.left = '100%'; style.zIndex = '0'; } Stack.prototype.show = function show() { elements.shadow_properties.style.display = 'none'; elements.element_properties.style.display = 'block'; if (this.id === 'element') { elements.zIndex.style.display = 'none'; elements.transform_rotate.style.display = 'none'; } else { elements.zIndex.style.display = 'block'; elements.transform_rotate.style.display = 'block'; } this.subject.setAttribute('data-active', 'subject'); var style = this.container.style; style.left = '0'; style.zIndex = '10'; Tool.setActiveClass(this.id); } function init() { var elem, size; var layerManager = getElemById("layer_manager"); var layerMenu = getElemById("layer_menu"); var container = getElemById("stack_container"); elements.shadow_properties = getElemById('shadow_properties'); elements.element_properties = getElemById('element_properties'); elements.transform_rotate = getElemById('transform_rotate'); elements.zIndex = getElemById('z-index'); elem = document.querySelectorAll('#layer_menu [data-type="subject"]'); size = elem.length; for (var i = 0; i < size; i++) { var S = new Stack(elem[i]); stacks[elem[i].id] = S; container.appendChild(S.container); Tool.addCssClass(elem[i].id); } active.stack = stacks['element']; stacks['element'].show(); layerManager.addEventListener("click", mouseEvents); layerMenu.addEventListener("click", mouseEvents); ButtonManager.subscribe("before", function(value) { if (value === false && active.stack === stacks['before']) setActiveStack(stacks['element']) if (value === true && active.stack !== stacks['before']) setActiveStack(stacks['before']) }); ButtonManager.subscribe("after", function(value) { if (value === false && active.stack === stacks['after']) setActiveStack(stacks['element']) if (value === true && active.stack !== stacks['after']) setActiveStack(stacks['after']) }); } return { init : init } })(); /* * OutputManager */ var OutputManager = (function OutputManager() { var classes = []; var buttons = []; var active = null; var menu = null; var button_offset = 0; var crateOutputNode = function(topic, property) { var prop = document.createElement('div'); var name = document.createElement('span'); var value = document.createElement('span'); var pmatch = property.match(/(^([a-z0-9\-]*)=\[([a-z0-9\-\"]*)\])|^([a-z0-9\-]*)/i); name.textContent = '\t' + pmatch[4]; if (pmatch[3] !== undefined) { name.textContent = '\t' + pmatch[2]; value.textContent = pmatch[3] + ';'; } name.textContent += ': '; prop.className = 'css-property'; name.className = 'name'; value.className = 'value'; prop.appendChild(name); prop.appendChild(value); classes[topic].node.appendChild(prop); classes[topic].line[property] = prop; classes[topic].prop[property] = value; } var OutputClass = function OutputClass(node) { var topic = node.getAttribute('data-topic'); var prop = node.getAttribute('data-prop'); var name = node.getAttribute('data-name'); var properties = prop.split(' '); classes[topic] = {}; classes[topic].node = node; classes[topic].prop = []; classes[topic].line = []; classes[topic].button = new Button(topic); var open_decl = document.createElement('div'); var end_decl = document.createElement('div'); open_decl.textContent = name + ' {'; end_decl.textContent = '}'; node.appendChild(open_decl); for (var i in properties) crateOutputNode(topic, properties[i]); node.appendChild(end_decl); } var Button = function Button(topic) { var button = document.createElement('div'); button.className = 'button'; button.textContent = topic; button.style.left = button_offset + 'px'; button_offset += 100; button.addEventListener("click", function() { toggleDisplay(topic); }) menu.appendChild(button); return button; } var toggleDisplay = function toggleDisplay(topic) { active.button.removeAttribute('data-active'); active.node.style.display = 'none'; active = classes[topic]; active.node.style.display = 'block'; active.button.setAttribute('data-active', 'true'); } var toggleButton = function toggleButton(topic, value) { var display = (value === true) ? 'block' : 'none'; classes[topic].button.style.display = display; if (value === true) toggleDisplay(topic); else toggleDisplay('element'); } var updateProperty = function updateProperty(topic, property, data) { try { classes[topic].prop[property].textContent = data + ';'; } catch(error) { // console.log("ERROR undefined : ", topic, property, data); } } var toggleProperty = function toggleProperty(topic, property, value) { var display = (value === true) ? 'block' : 'none'; try { classes[topic].line[property].style.display = display; } catch(error) { // console.log("ERROR undefined : ",classes, topic, property, value); } } var init = function init() { menu = getElemById('menu'); var elem = document.querySelectorAll('#output .output'); var size = elem.length; for (var i = 0; i < size; i++) OutputClass(elem[i]); active = classes['element']; toggleDisplay('element'); ButtonManager.subscribe("before", function(value) { toggleButton('before', value); }); ButtonManager.subscribe("after", function(value) { toggleButton('after', value); }); } return { init : init, updateProperty : updateProperty, toggleProperty : toggleProperty } })(); /** * Init Tool */ var init = function init() { ButtonManager.init(); OutputManager.init(); ColoPicker.init(); SliderManager.init(); LayerManager.init(); PreviewMouseTracking.init("preview"); Tool.init(); } return { init : init } })();
Related Tool: Box Shadow CSS Generator
© 2005–2018 Mozilla Developer Network and individual contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Box-shadow_generator