Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Генератор теней

Этот инструмент позволяет вам создавать CSS box-shadow эффекты, добавлять тени вашим элементам.

box-shadow generator

HTML Content

<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=[&quot;&quot;] 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=[&quot;&quot;] position=[absolute] width height top left z-index background-color box-shadow transform -webkit-transform -ms-transform">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

CSS Content

/*  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;
}

JavaScript Content



'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
	}

})();


 

Метки документа и участники

 Внесли вклад в эту страницу: bychek.ru
 Обновлялась последний раз: bychek.ru,