Showing preview only (207K chars total). Download the full file or copy to clipboard to get everything.
Repository: mrflix/LayerStyles
Branch: master
Commit: 0f8679a39ce7
Files: 23
Total size: 199.2 KB
Directory structure:
gitextract_kja_9fna/
├── .project
├── README.markdown
├── builder.html
├── css/
│ ├── index.css
│ └── style.css
├── index.html
└── js/
├── application.js
├── codebox.js
├── color.js
├── colorpicker.js
├── css.js
├── gradienteditor.js
├── localization.js
├── numbers.js
├── style.js
├── styleStore.js
├── tools.js
├── ui.js
├── universe.js
└── zeroclipboard/
├── ZeroClipboard.as
├── ZeroClipboard.fla
├── ZeroClipboard.js
└── ZeroClipboard.swf
================================================
FILE CONTENTS
================================================
================================================
FILE: .project
================================================
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>LayerStyles</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>
================================================
FILE: README.markdown
================================================
Layer Styles
============
A HTML5 app for creating CSS3 in a intuitive way.
Highlights
----------
- Colorpicker can pick any color of the element your working on
- Drag and Drop images onto the page to use them as a background or to pick their colors
- Color Swatches, Gradients and Styles are locally stored
================================================
FILE: builder.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Layer Styles</title>
<link rel="icon" type="image/png" href="favicon.png" />
<script type="text/javascript" src="js/modernizr-1.7.min.js"></script>
<link rel="stylesheet" href="css/style.css" type="text/css" />
</head>
<body>
<div id="main" class="box vertical flex">
<span id="codeBoxToggle">CSS Code</span>
<div id="workspace" class="box vertical flex">
<div id="overlay"></div>
<canvas id="innerShadow_universe"></canvas>
<canvas id="parallel_universe"></canvas>
<div id="background_layer" class="flex"></div>
<div id="layer"><div id="resize" class="resize"></div></div>
</div> <!-- /workspace -->
<div id="codeBox" class="paper">
<div class="dragger y"><div class="dragBox"></div></div>
<div class="body">
<div class="scroll paper">
<div id="copyCode">copy</div>
<div id="colorSwitch" class="toggle">
<div class="slidePanel">
<span class="left">rgb</span><span class="button"></span><span class="right">hex</span>
</div>
</div>
<code></code>
</div>
</div>
</div> <!-- /codeBox -->
</div> <!-- /main -->
<div id="layerstyle">
<div id="headerBg"></div>
<div id="dialog" class="window">
<div class="head moveable">
<h2>Layer Style</h2>
</div>
<div class="body">
<div class="main">
<div id="nav">
<ul>
<li>Styles</li>
<li class="nav-dropShadow active"><input type="checkbox" checked="checked">Drop Shadow</li>
<li class="nav-innerShadow"><input type="checkbox">Inner Shadow</li>
<li class="nav-background"><input type="checkbox" checked="checked">Background</li>
<li class="nav-border"><input type="checkbox" checked="checked">Border</li>
<li class="nav-borderRadius"><input type="checkbox">Border Radius</li>
</ul>
</div>
<div class="styles">
<div id="holder" class="holder">
<div>
<h3>Styles</h3>
<div id="stylePresets" class="border_box">
</div>
</div>
<div id="dropShadow">
<h3>Drop Shadow</h3>
<label>Color:</label>
<div>
<div class="color_field"></div>
</div>
<label for="ds-opacity">Opacity:</label>
<div>
<div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="opacity" id="ds-opacity" type="text" data-min="0" data-max="100" data-restrict="digits" value="75">
%
</div>
<label class="angle_holder" for="ds-angle">Angle:</label>
<div>
<div class="pot"><div class="pointer"><div class="dot"></div><div class="line"></div></div></div>
<div class="angle_holder">
<input class="angle" id="ds-angle" type="text" data-min="0" data-max="360" data-restrict="digits" value="90">
°
<input type="checkbox" class="globalLight" id="ds-globalLight"><label for="ds-globalLight">Use Global Light</label>
</div>
</div>
<label for="ds-distance">Distance:</label>
<div>
<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="distance" id="ds-distance" type="text" data-min="0" data-max="100" value="1">
px
</div>
<label for="ds-blur">Blur:</label>
<div>
<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="blur" id="ds-blur" type="text" data-min="0" data-max="100" value="5">
px
</div>
<label for="ds-size">Size:</label>
<div>
<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="size" id="ds-size" type="text" data-min="0" data-max="255" value="0">
px
</div>
<div class="clear"></div>
</div>
<div id="innerShadow">
<h3>Inner Shadow</h3>
<label>Color:</label>
<div>
<div class="color_field"></div>
</div>
<label for="is-opacity">Opacity:</label>
<div>
<div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="opacity" id="is-opacity" type="text" data-min="0" data-max="100" data-restrict="digits" value="90">
%
</div>
<label class="angle_holder" for="is-angle">Angle:</label>
<div>
<div class="pot"><div class="pointer"><div class="dot"></div><div class="line"></div></div></div>
<div class="angle_holder">
<input class="angle" id="is-angle" type="text" data-min="0" data-max="360" data-restrict="digits" value="90">
°
<input type="checkbox" class="globalLight" id="is-globalLight"><label for="is-globalLight">Use Global Light</label>
</div>
</div>
<label for="is-distance">Distance:</label>
<div>
<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="distance" id="is-distance" type="text" data-min="0" data-max="100" value="1">
px
</div>
<label for="is-blur">Blur:</label>
<div>
<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="blur" id="is-blur" type="text" data-min="0" data-max="100" value="0">
px
</div>
<label for="is-size">Size:</label>
<div>
<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="size" id="is-size" type="text" data-min="0" data-max="255" value="0">
px
</div>
<div class="clear"></div>
</div>
<div id="background">
<h3>Background</h3>
<label for="bg-opacity">Opacity:</label>
<div>
<div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="opacity" id="bg-opacity" type="text" data-min="0" data-max="100" value="100">
%
</div>
<label>Gradient</label>
<div>
<div class="gradientField"></div>
<input type="checkbox" class="reverse" id="bg-reverse"><label for="bg-reverse">Reverse</label>
</div>
<label>Style</label>
<div>
<select id="background_style">
<option value="linear">Linear</option>
<option value="reflected">Reflected</option>
<option value="contain">Radial - contain</option>
<option value="cover">Radial - cover</option>
</select>
</div>
<label class="angle_holder" for="bg-angle">Angle:</label>
<div>
<div class="pot"><div class="pointer"><div class="dot"></div><div class="line"></div></div></div>
<div class="angle_holder">
<input class="angle" id="bg-angle" type="text" data-min="0" data-max="360" value="90">
°
<input type="checkbox" class="globalLight" id="bg-globalLight"><label for="bg-globalLight">Use Global Light</label>
</div>
</div>
<div class="clear"></div>
</div>
<div id="border">
<h3>Border</h3>
<label>Color:</label>
<div>
<div class="color_field"></div>
</div>
<label for="bd-opacity">Opacity:</label>
<div>
<div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="opacity" id="bd-opacity" type="text" data-min="0" data-max="100" value="100">
%
</div>
<label for="bd-size">Size:</label>
<div>
<div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="size" id="bd-size" type="text" data-min="0" data-max="10" value="1">
px
</div>
<label>Style:</label>
<div id="border_styles" class="previews">
<div id="border_style_solid" title="solid" data-style="solid" class="active"></div>
<div id="border_style_dashed" title="dashed" data-style="dashed"></div>
<div id="border_style_dotted" title="dotted" data-style="dotted"></div>
<div id="border_style_double" title="double" data-style="double"></div>
</div>
<div class="clear"></div>
</div><!-- /border -->
<div id="borderRadius">
<h3>Border Radius</h3>
<label for="br-radius">Radius:</label>
<div>
<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
<input class="radius" id="br-radius" type="text" data-min="0" data-max="200" value="0">
<span class="options" id="border_radius_unit"><span id="border_radius_pixel" data-unit="px" class="active">px</span><span id="border_radius_percent" data-unit="%">%</span></span>
</div>
<label>Corners:</label>
<div id="border_radius_preview">
<div id="topLeft" class="active"></div>
<div id="topRight" class="active"></div>
<div id="bottomRight" class="active"></div>
<div id="bottomLeft" class="active"></div>
</div>
<div class="clear"></div>
</div>
</div>
</div>
<div class="clear"></div>
</div>
<div class="controls">
<button id="ok">OK</button>
<button id="cancel">Cancel</button>
<button id="new_style">New Style...</button>
</div>
</div>
</div>
<div id="gradient_editor" class="window">
<div class="head moveable">
<h2>Gradient Editor</h2>
</div>
<div class="body">
<div class="static_right">
<div class="main">
<div class="holder">
<h3>Presets</h3>
<div id="gradient_presets_holder" class="border_box">
<div id="gradient_presets">
</div>
</div>
</div>
</div>
<div class="controls sidebar">
<button id="gradient_ok">OK</button>
<button id="gradient_cancel">Cancel</button>
</div>
<div class="clear"></div>
</div>
<div class="static_right">
<div class="main">
<div class="static_left">
<span>Name:</span><input id="gradient_name" type="text">
</div>
</div>
<div class="controls sidebar">
<button id="gradient_new">New</button>
</div>
<div class="clear"></div>
</div>
<div class="holder">
<h3>Gradient</h3>
<div id="gradient_holder">
<div class="frame">
<div id="gradient">
</div>
</div>
</div>
<div id="stops" class="holder">
<h3>Stops</h3>
<div id="color_stops">
<div class="disabled">
<span>Color:</span><div id="stop_color" class="color_field"></div>
</div>
<div class="disabled">
<label for="stop_location">Location:</label>
<input type="text" id="stop_location" data-min="0" data-max="100" data-restrict="digits" disabled="disabled">%
</div>
<button id="remove_stop" disabled="disabled">Delete</button>
</div>
</div>
</div>
</div>
</div>
<div id="colorpicker" class="window">
<div class="head moveable">
<h2>Colorpicker</h2>
</div>
<div class="body">
<div class="main">
<div id="color_field" class="border_box">
<canvas id="field" width="256" height="256"></canvas>
<canvas id="circle" class="colorcircle" width="256" height="256"></canvas>
</div>
<div id="color_slider">
<canvas class="border_box" width="19" height="256"></canvas>
<div>
<div class="arrow left"><div class="spike"></div><div class="rear"></div></div>
<div class="arrow right"><div class="spike"></div><div class="rear"></div></div>
</div>
</div>
<div class="color_preview lightbox">
<label>new</label>
<div id="new_color"></div>
<label>current</label>
<div id="current_color"></div>
</div>
<div class="color_inputs">
<ul>
<li>
<input type="radio" id="hsb_h-radio" name="color" value="hsb_h">
<label for="hsb_h-radio">H:</label>
<input id="hsb_h" type="text" data-min="0" data-max="360" data-restrict="digits" value="0">
°
</li>
<li>
<input type="radio" id="hsb_s-radio" name="color" value="hsb_s">
<label for="hsb_s-radio">S:</label>
<input id="hsb_s" type="text" data-min="0" data-max="100" data-restrict="digits" value="0">
%
</li>
<li>
<input type="radio" id="hsb_b-radio" name="color" value="hsb_b" checked="checked">
<label for="hsb_b-radio">B:</label>
<input id="hsb_b" type="text" data-min="0" data-max="100" data-restrict="digits" value="0">
%
</li>
</ul>
<ul>
<li>
<input type="radio" id="rgb_r-radio" name="color" value="rgb_r">
<label for="rgb_r-radio">R:</label>
<input id="rgb_r" type="text" data-min="0" data-max="255" data-restrict="digits" value="0">
</li>
<li>
<input type="radio" id="rgb_g-radio" name="color" value="rgb_g">
<label for="rgb_g-radio">G:</label>
<input id="rgb_g" type="text" data-min="0" data-max="255" data-restrict="digits" value="0">
</li>
<li>
<input type="radio" id="rgb_b-radio" name="color" value="rgb_b">
<label for="rgb_b-radio">B:</label>
<input id="rgb_b" type="text" data-min="0" data-max="255" data-restrict="digits" value="0">
</li>
</ul>
<div id="hex_holder">
<label for="hex">#</label>
<input type="text" id="hex" size="10" maxlength="6" data-restrict="hexcode">
</div>
</div>
</div>
<div class="controls">
<button id="color_ok">OK</button>
<button id="color_cancel">Cancel</button>
<button id="color_add">Add to Swatches</button>
<div id="swatches_holder">
<div id="swatches" class="paint_bucket">
</div>
</div>
</div>
</div>
</div><!-- /ColorPicker -->
</div> <!-- /LayerStyle -->
<script type="text/javascript" src="js/jquery-1.6.min.js"></script>
<script type="text/javascript" src="js/ui.js"></script>
<script type="text/javascript" src="js/zeroclipboard/ZeroClipboard.js"></script>
<script type="text/javascript" src="js/localization.js"></script>
<script type="text/javascript" src="js/color.js"></script>
<script type="text/javascript" src="js/numbers.js"></script>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/css.js"></script>
<script type="text/javascript" src="js/style.js"></script>
<script type="text/javascript" src="js/colorpicker.js"></script>
<script type="text/javascript" src="js/gradienteditor.js"></script>
<script type="text/javascript" src="js/codebox.js"></script>
<script type="text/javascript" src="js/universe.js"></script>
<script type="text/javascript" src="js/styleStore.js"></script>
<script type="text/javascript" src="js/application.js"></script>
</body>
</html>
================================================
FILE: css/index.css
================================================
* { margin: 0; padding: 0; }
html { height: 100%; }
body {
font: 12px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif;
background-color: #fcfcfc;
background-image: -moz-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
background-image: -webkit-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
background-image: -o-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
background-image: -ms-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
}
#arche {
padding-top: 55px;
width: 556px;
margin: 0 auto;
text-transform: uppercase;
text-shadow: 0 1px white;
z-index: 200;
position: relative;
-moz-transition: 320ms;
-webkit-transition: 320ms;
transition: 320ms;
}
h1 span { color: #349ae3; text-transform: none; font-size: 16px; }
h3 { color: #666; font-weight: normal; }
a { text-decoration: none; color: #349ae3; }
em { font-weight: bold; font-style: normal; }
img { border: none; }
#header {
margin-top: 14px;
padding-left: 100px;
position: relative;
background: url(../img/logo.png) no-repeat 24px 5px;
}
.hero {
top: 0;
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
-moz-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
-webkit-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
position: relative;
}
#ready {
margin: 17px 0 21px;
display: none;
}
#ready .hero {
-moz-transition: 240ms ease;
-webkit-transition: 240ms ease;
transition: 240ms ease;
}
#ready:hover .hero {
top: 3px;
-moz-box-shadow: 0 12px 40px 8px rgba(0,0,0,.20), 0 0 0 1px rgba(0,0,0,.16);
-webkit-box-shadow: 0 12px 40px 8px rgba(0,0,0,.20), 0 0 0 1px rgba(0,0,0,.16);
box-shadow: 0 12px 40px 8px rgba(0,0,0,.20), 0 0 0 1px rgba(0,0,0,.16);
}
#not-ready {
margin: 17px 0 21px;
display: none;
position: relative;
}
#not-ready .holder {
left: 153px;
top: 76px;
width: 276px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.21), 0 15px 40px 10px rgba(0, 0, 0, 0.34);
-webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.21), 0 15px 40px 10px rgba(0, 0, 0, 0.34);
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.21), 0 15px 40px 10px rgba(0, 0, 0, 0.34);
position: absolute;
text-shadow: none;
text-transform: none;
}
#not-ready .upper {
padding: 13px;
border: 1px solid #A6281C;
background: #F03432;
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
-moz-box-shadow: 0 0 0 1px #F25146 inset;
-webkit-box-shadow: 0 0 0 1px #F25146 inset;
box-shadow: 0 0 0 1px #F25146 inset;
}
#not-ready h2 { padding-bottom: 13px; font-size: 14px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.21); border-bottom: 1px solid rgba(0, 0, 0, 0.34); }
.features { border-top: 1px solid rgba(255,255,255,.13); padding-top: 8px; line-height: 2; }
.features span {
display: none;
padding: 1px 8px;
color: white;
white-space: nowrap;
background: #F25146;
text-shadow: 0 1px 0 rgba(255,255,255,0.21);
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
}
#not-ready .bottom {
padding: 13px;
color: white;
text-shadow: 0 2px black;
background: black;
background: rgba(0,0,0,.8);
-webkit-border-bottom-left-radius: 4px;
-webkit-border-bottom-right-radius: 4px;
-moz-border-radius-bottomleft: 4px;
-moz-border-radius-bottomright: 4px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.js.nativejson.flexbox.canvas.rgba.borderradius.boxshadow.cssgradients #ready { display: block; }
.no-js #not-ready,
.no-flexbox #not-ready,
.no-canvas #not-ready,
.no-rgba #not-ready,
.no-borderradius #not-ready,
.no-boxshadow #not-ready,
.no-cssgradients #not-ready { display: block; }
.no-js .feature-js { display: inline; }
.no-nativejson .feature-json { display: inline; }
.no-flexbox .feature-flexbox { display: inline; }
.no-canvas .feature-canvas { display: inline; }
.no-rgba .feature-rgba { display: inline; }
.no-borderradius .feature-borderradius { display: inline; }
.no-boxshadow .feature-boxshadow { display: inline; }
.no-cssgradients .feature-cssgradients { display: inline; }
footer {
padding: 0 21px;
color: rgba(0,0,0,.34);
}
================================================
FILE: css/style.css
================================================
* { margin: 0; padding: 0; }
body, html { height: 100%; overflow: hidden; }
body {
width: 100%;
font: 12px/14px "Helvetica Neue", Helvetica, Arial, sans-serif;
background: url(../img/transparent.gif);
}
.box {
display: -moz-box;
display: -webkit-box;
display: box;
}
.box.vertical {
-moz-box-orient: vertical;
-webkit-box-orient: vertical;
box-orient: vertical;
}
.flex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
ul { list-style: none; }
#helper { top: 5px; right: 5px; padding: 8px 13px; position: absolute; z-index: 9999; background: rgba(0,0,0,.5);
-moz-border-radius: 13px;
-webkit-border-radius: 13px;
border-radius: 13px;
}
#layer {
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
width: 300px;
height: 300px;
position: absolute;
z-index: 99;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
opacity: 1;
}
#resize { bottom: -15px; right: -15px; width: 30px; height: 30px; position: absolute; }
#layer.borderRadius:hover #resize { border-right: 1px solid rgba(0, 0, 0, 0.1); border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
#main { position: relative; height: 100%; width: 100%; }
#workspace { position: relative; }
#parallel_universe { position: absolute; z-index: -1; }
#innerShadow_universe { position: absolute; z-index: -1; }
#background_layer {
background: -moz-linear-gradient(top, #e2e2e2, #ababab);
background: -webkit-gradient(linear, left top, left bottom, from(#e2e2e2), to(#ababab));
background: -o-linear-gradient(top, #e2e2e2, #ababab);
display: block;
}
#codeBoxToggle {
bottom: 0;
left: 0;
padding: 5px 13px 4px;
line-height: 18px;
color: rgba(0, 0, 0, 0.75);
background: rgba(0,0,0,.08);
border-radius: 2px 2px 0 0;
position: absolute;
cursor: pointer;
display: inline-block;
z-index: 101;
-moz-transition: background-color 240ms ease;
-webkit-transition: background-color 240ms ease;
transition: background-color 240ms ease;
}
#codeBoxToggle:hover {
background: rgba(0,0,0,.13);
}
#overlay { width: 100%; height: 100%; position: absolute; top: 0; background-color: transparent;
-moz-transition: background-color 240ms ease;
-webkit-transition: background-color 240ms ease;
transition: background-color 240ms ease;
}
.dragging #overlay { z-index: 101; background-color: rgba(0,0,0,.21); }
.pick #overlay { z-index: 100; cursor: url(../img/eyedropper.gif) 0 15, auto; }
#infoButton {
position: absolute;
left: 0;
padding: 13px;
color: black;
text-decoration: none;
text-transform: uppercase;
opacity: 0.21;
z-index: 99;
display: block;
-moz-transition: 240ms;
-webkit-transition: 240ms;
transition: 240ms;
}
#infoButton:hover { opacity: 0.55; }
#codeBox {
height: 0;
position: relative;
overflow: hidden;
background-position: 0 2px;
-webkit-transition: 300ms ease-out;
-moz-transition: 300ms ease-out;
transition: 300ms ease-out;
}
#codeBox.resizing {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
#codeBox .dragger.y {
top: 0;
height: 21px;
background: -moz-linear-gradient(#9E9E9E, #999);
background: -webkit-gradient(linear, center top, center bottom, from(#9E9E9E), to(#999));
background: -webkit-linear-gradient(#9E9E9E, #99);
border-bottom: 1px solid #666;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
display: block;
position: relative;
z-index: 1;
}
#copyCode {
top: 21px;
left: 1px;
width: 78px;
height: 15px;
color: #444;
font-family: "Consolas", "Monaco", monospace;
line-height: 15px;
font-size: 10px;
text-align: center;
border: 1px solid #edc59c;
border-radius: 4px;
background-image: -moz-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
background-image: -webkit-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
background-size: 4px 4px;
position: absolute;
cursor: pointer;
}
#copyCode:active { color: black; }
#copyCode embed { left: 0; position: absolute; outline: none; }
#colorSwitch {
top: 41px;
left: 1px;
width: 78px;
height: 15px;
color: #444;
border: 1px solid #edc59c;
border-radius: 4px;
overflow: hidden;
position: absolute;
}
.toggle { cursor: pointer; }
#colorSwitch .slidePanel {
width: 150%;
height: 100%;
left: -50%;
margin: 1px;
position: absolute;
-moz-transition: 320ms ease;
-webkit-transition: 320ms ease;
}
#colorSwitch.moving .slidePanel {
-moz-transition: none;
-webkit-transition: none;
}
#colorSwitch .button {
top: 0;
left: 33.33%;
width: 35px;
height: 11px;
position: absolute;
border: 1px solid #edc59c;
border-radius: 3px;
background-image: -moz-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
background-image: -webkit-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
background-size: 4px 4px;
}
#colorSwitch .left,
#colorSwitch .right { right: 0; width: 33.33%; height: 100%; line-height: 13px; font-size: 10px; text-align: center; position: absolute; }
#colorSwitch .left { left: 0; right: auto; }
#codeBox .body {
color: #444;
height: 100%;
border-top: 1px solid rgba(0,0,0,.13);
overflow: auto;
position: relative;
}
.paper {
background-color: #ffe4b5;
/* lines */
background-image:
-moz-linear-gradient(left, transparent 82px, rgba(128,0,0,.08) 82px, rgba(128,0,0,.08) 82px, transparent 83px),
-moz-repeating-linear-gradient(transparent, transparent 19px, rgba(128, 0, 0, 0.08) 19px, rgba(128, 0, 0, 0.08) 20px);
background-image:
-webkit-linear-gradient(left, transparent 82px, rgba(128,0,0,.08) 82px, rgba(128,0,0,.08) 82px, transparent 83px),
-webkit-repeating-linear-gradient(transparent, transparent 19px, rgba(128, 0, 0, 0.08) 19px, rgba(128, 0, 0, 0.08) 20px);
}
#codeBox .scroll {
padding: 20px 0 0 108px;
}
#codeBox code {
padding-bottom: 20px;
border: none;
font-family: "Consolas", monospace;
line-height: 20px;
display: block;
}
.dragger { position: absolute; z-index: 100; }
.dragger.x { width: 10px; left: -5px; top: 0; height: 100%; cursor: w-resize; }
.dragger.y { width: 100%; top: -5px; left: 0; height: 10px; cursor: n-resize; }
.dragBox { bottom: 0; left: 5px; height: 20px; width: 20px; border: 1px solid rgba(0,0,0,.13); background: url(../img/dragger.png) no-repeat 6px 6px; position: absolute; }
.dragger.y .dragBox {
bottom: -1px;
border: none;
-moz-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-moz-transform-origin: center center;
-webkit-transform-origin: center center;
transform-origin: center center;
}
.moveable { cursor: move; }
#layerstyle {
top: 11px;
left: 51px;
width: 556px;
height: 393px;
color: black;
background: #EDEDED;
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
-moz-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
-webkit-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
position: absolute;
z-index: 100;
display: block;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
#headerBg {
top: 0;
left: 0;
width: 100%;
height: 24px;
border-top: 1px solid #E2E2E2;
border-bottom: 1px solid #515151;
background: -moz-linear-gradient(#CFCFCF, #A8A8A8);
background: -webkit-gradient(linear, center top, center bottom, from(#CFCFCF), to(#A8A8A8));
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
position: absolute;
}
.window { top: 0; width: 100%; position: absolute; }
.window .head {
padding: 6px;
position: relative;
}
.window .head h2 {
font-size: 13px;
font-weight: normal;
text-align: center;
color: black;
text-shadow: 0 1px 0 #cfcfcf;
}
.window .head > button {
position: absolute;
left: 3px;
top: 3px;
width: auto;
padding: 1px 9px;
text-shadow: 0 1px 0 white;
background: -moz-linear-gradient(top, #ebebeb, #d7d7d7);
background: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#d7d7d7));
border: 1px solid #999999;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 0 rgba(255,255,255,0.5), 0 1px 0 white inset;
-webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.5), 0 1px 0 white inset;
box-shadow: 0 1px 0 rgba(255,255,255,0.5), 0 1px 0 white inset;
cursor: pointer;
}
.window .body { padding: 15px 10px; position: relative; }
.inactive {
color: gray;
}
#dialog { visibility: hidden; }
.main { width: 82%; float: left; font-size: 10px; }
.main > .styles { width: 72%; float: left; }
#holder { margin: 0 16px; }
#holder > div { width: 100%; visibility: hidden; position: absolute; top: 0; padding: 12px 0; border: 1px solid #909090; }
#holder > div.active { visibility: visible; }
.holder { position: relative; }
.holder h3 { left: 9px; top: -8px; padding: 0 3px 0 2px; font-size: 10px; position: absolute; background: #ededed; }
.styles > div > div > label { width: 22%; padding-top: 1px; margin-right: 2%; text-align: right; float: left; clear: right; }
.styles label + div { width: 75%; float: right; }
.styles label, .styles label + div { margin-top: 2px; }
.styles .color_field { height: 13px; width: 33px; border: 1px solid #909090; background: white; cursor: pointer; }
.styles input[type=checkbox] { margin: 0 6px; vertical-align: middle; width: auto; }
.styles input[type=checkbox] + label { vertical-align: middle; }
.styles .angle_holder { top: 13px; position: relative; display: inline-block; vertical-align: top; }
input[type=text] {
width: 40px;
padding: 1px;
font-size: 10px;
border: 1px solid #909090;
border-bottom-width: 0;
-moz-box-shadow: inset 0 0 0 1px #bababa, 0 1px 0 rgba(0,0,0,.04);
-webkit-box-shadow: inset 0 0 0 1px #bababa, 0 1px 0 rgba(0,0,0,.04);
box-shadow: inset 0 0 0 1px #bababa, 0 1px 0 rgba(0,0,0,.04);
}
.styles .slider { width: 100px; margin: 0 5px 0 3px; }
#stylePresets { margin: -2px 9px 0; height: 230px; overflow: auto; }
#stylePresets .swatch { width: 31px; height: 31px; border-right: 1px solid #909090; border-bottom: 1px solid #909090; float: left;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
}
#stylePresets .swatch.active { border: 2px solid black; }
#stylePresets .swatch > div { width: 17px; height: 17px; margin: 7px 0 0 7px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
#stylePresets .swatch.active > div { margin: 5px 0 0 5px; }
#holder #background { }
.gradientField {
margin: 2px 0;
width: 109px;
height: 15px;
vertical-align: middle;
border: 1px solid black;
display: inline-block;
cursor: pointer;
}
.previews > div { margin: 2px 2px 2px 0; width: 24px; height: 24px; border: 1px solid black; display: inline-block; opacity: 0.3; }
.previews > .active { opacity: 1; background-color: #A7D4F6; }
.inactive .previews > .active { background-color: rgba(0,0,0,.08); border-color: gray; }
#border .previews > div { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
#border_style_dotted { border-style: dotted; }
#border_style_dashed { border-style: dashed; }
#border_style_double { border: 3px double black; }
#border_radius_preview {
width: 104px;
height: 104px;
margin: 4px 3px;
float: left;
border-color: rgba(0,0,0,.25);
position: relative;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
overflow: hidden;
}
#border_radius_preview > div {
width: 50%;
height: 50%;
float: left;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
}
#border_radius_preview #bottomRight { float: right; border-bottom: 1px solid rgba(0,0,0,.25); border-right: 1px solid rgba(0,0,0,.25); }
#border_radius_preview #topLeft { border-top: 1px solid rgba(0,0,0,.25); border-left: 1px solid rgba(0,0,0,.25); border-bottom: 1px dotted rgba(0,0,0,.25); border-right: 1px dotted rgba(0,0,0,.25); }
#border_radius_preview #topRight { border-top: 1px solid rgba(0,0,0,.25); border-right: 1px solid rgba(0,0,0,.25); border-bottom: 1px dotted rgba(0,0,0,.25); }
#border_radius_preview #bottomLeft { border-bottom: 1px solid rgba(0,0,0,.25); border-left: 1px solid rgba(0,0,0,.25); border-right: 1px dotted rgba(0,0,0,.25); }
#border_radius_preview > div.active { background: #A7D4F6; }
.inactive #border_radius_preview > div.active { background: rgba(0,0,0,.08); }
.options {
-moz-box-shadow: 0 2px white;
-webkit-box-shadow: 0 2px white;
box-shadow: 0 2px white;
cursor: pointer;
}
.options span:first-child { border-right: none; }
.options span:last-child { border-left: none; }
.options span {
padding: 0 4px;
border: 1px solid rgba(0,0,0,.5);
background: -moz-linear-gradient(#C1C1C1, #D4D4D4);
background: -webkit-linear-gradient(#C1C1C1, #D4D4D4);
background: linear-gradient(#C1C1C1, #D4D4D4);
-moz-box-shadow: 0 1px white inset;
-webkit-box-shadow: 0 1px white inset;
box-shadow: 0 1px white inset;
}
.options span.active {
border: 1px solid rgba(0,0,0,.5);
background: -moz-linear-gradient(#999999, #BBBBBB);
background: -webkit-linear-gradient(#999999, #BBBBBB);
background: linear-gradient(#999999, #BBBBBB);
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.inactive .options span { opacity: 0.5; }
#nav { width: 28%; height: 100%; float: left; cursor: default; }
#nav ul {
border: 1px solid #909090;
-moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,.3);
-webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.3);
box-shadow: inset 1px 1px 0 rgba(0,0,0,.3);
}
#nav li { margin: 0 0 0 1px; padding: 4px 6px; border-bottom: 1px solid white; cursor: pointer; }
#nav li input { margin-right: 5px; vertical-align: bottom; cursor: pointer; }
#nav li.active { background: #b5d5ff; font-weight: bold; }
#nav li:first-child { padding-bottom: 6px;
-moz-box-shadow: inset 0 -1px 0 black;
-webkit-box-shadow: inset 0 -1px 0 black;
box-shadow: inset 0 -1px 0 black;
}
#nav li:first-child + li { padding-top: 5px; border-top: 1px solid #909090;
-moz-box-shadow: inset 0 1px 0 black;
-webkit-box-shadow: inset 0 1px 0 black;
box-shadow: inset 0 1px 0 black;
}
.controls { width: 18%; float: right; }
.controls > div { text-align: center; }
.controls > div input { margin-right: 2px; }
#colorpicker { visibility: hidden; }
#colorpicker .body { padding-top: 9px; }
#colorpicker .main { width: 75%; height: 294px; margin-top: 21px; position: relative; }
#color_field { height: 256px; width: 256px; position: absolute; }
#field, #circle { position: absolute; }
#circle { z-index: 999; }
#color_slider { left: 259px; top: 2px; width: 44px; height: 256px; position: absolute; }
#color_slider canvas {
top: -2px;
left: 11px;
height: 256px;
width: 19px;
position: absolute;
}
.border_box { border-color: #909090 #909090 #e4e4e4 #909090; border-width: 2px 1px 1px 2px; border-style: solid; }
.lightbox { border: 1px solid #909090; border-bottom-color: #e4e4e4; }
#color_slider > div { left: 11px; top: 256px; width: 21px; position: absolute; }
#color_slider > div > .arrow.right { right: -3px; }
#color_slider > div > .arrow.left { left: -9px; }
#color_slider .arrow { top: -4px; position: absolute; }
#color_slider .arrow div { border: 1px solid #747474; background: white; position: absolute; }
#color_slider .arrow .rear { width: 4px; height: 6px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
#color_slider .arrow .spike { top: 1px; width: 4px; height: 4px;
-moz-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
#color_slider .arrow.left .rear { border-right-width: 0; }
#color_slider .arrow.left .spike { left: 1px; }
#color_slider .arrow.right .rear { border-left-width: 0; left: 2px; }
.color_preview { top: 4px; left: 304px; width: 60px; position: absolute; }
.color_preview > div { height: 34px; background: black; border: 1px solid black; }
#new_color { border-bottom: none; }
#current_color { background: white; border-top: none; }
.color_preview > label { bottom: -14px; width: 100%; text-align: center; position: absolute; }
.color_preview > label:first-child { top: -20px; height: 20px; }
.color_inputs { top: 111px; left: 305px; width: 100px; position: absolute; font-size: 13px; }
.color_inputs ul { padding-bottom: 4px; }
.color_inputs li { margin: 2px 0 3px; display: inline-block; }
.color_inputs input[type=radio] { margin-right: 4px; }
.color_inputs span { width: 20px; display: inline-block; }
.color_inputs ul input[type=text] { width: 33px; height: 18px; margin-right: 2px; font-size: 13px; }
.color_inputs #hex_holder { margin: 2px 3px; }
.color_inputs #hex { height: 18px; margin-left: 4px; font-size: 13px; width: 68px; }
#colorpicker .controls { width: 25%; }
#swatches_holder { margin: 5px; background: #d6d6d6; border-top: 1px solid #909090; overflow: hidden; }
#swatches { padding-bottom: 12px; overflow: hidden; }
#swatches span {
width: 10px;
height: 11px;
border-right: 1px solid black;
border-bottom: 1px solid black;
float: left;
cursor: url(../img/eyedropper.gif) 0 15, auto;
}
.alt .swatch { cursor: url(../img/scissor.gif) 6 6, auto; }
#gradient_editor { visibility: hidden; }
/* overwritings */
#gradient_editor .holder { padding: 13px 9px 9px; border: 1px solid #909090; }
#gradient_editor .holder h3 { left: 16px; font-size: 13px; font-weight: normal; }
#gradient_editor input[type=text] { padding: 2px; font-size: 13px; }
#gradient_editor .static_right { margin-right: 105px; }
#gradient_editor .main { width: 100%; font-size: 13px; }
#gradient_editor .static_left { margin: 16px 4px 22px 56px; }
#gradient_editor .static_left > span { margin-left: -55px; line-height: 22px; float: left; }
#gradient_name { width: 100%; }
#gradient_new { margin-top: 17px; }
#gradient_presets_holder { height: 115px; overflow: auto; }
#gradient_presets div { width: 31px; height: 31px; border-right: 1px solid #909090; border-bottom: 1px solid #909090; float: left; }
#gradient_editor .sidebar { width: 89px; margin-right: -105px; }
#gradient_holder { padding: 12px 6px 34px; }
.frame { border: 1px solid #909090; }
#gradient { height: 25px; position: relative; }
#gradient div { cursor: default; }
#gradient .picker { position: absolute; }
#gradient .picker.top { top: -19px; }
#gradient .picker.bottom { top: 33px; }
#gradient .picker > div { position: absolute; }
#gradient .picker .arrow { left: -3px; top: 6px; height: 6px; width: 6px; border: 1px solid black;
-moz-box-shadow: -1px 0 #909090 inset;
-webkit-box-shadow: -1px 0 #909090 inset;
box-shadow: -1px 0 #909090 inset;
-moz-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
-moz-transform-origin: 2px 3px;
-webkit-transform-origin: 2px 3px;
transform-origin: 2px 3px;
}
#gradient .picker.bottom .arrow { top: -5px;
-moz-box-shadow: 0 1px #909090 inset;
-webkit-box-shadow: 0 1px #909090 inset;
box-shadow: 0 1px #909090 inset;
}
#gradient .picker.selected .arrow { background: black;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
#gradient .picker .box { left: -6px; height: 10px; width: 9px; background: #E4E4E4; border: 1px solid black; border-bottom: none;
-moz-box-shadow: -1px 0 #909090 inset;
-webkit-box-shadow: -1px 0 #909090 inset;
box-shadow: -1px 0 #909090 inset;
}
#gradient .picker.bottom .box { height: 9px; padding-top: 1px; border-bottom: 1px solid black; border-top: none;
-moz-box-shadow: 0 1px #909090 inset;
-webkit-box-shadow: 0 1px #909090 inset;
box-shadow: 0 1px #909090 inset;
}
#gradient .picker .color_field { height: 7px; width: 7px; border-width: 1px; border-style: solid; border-color: #E4E4E4 #909090 #909090 #E4E4E4; background: black; }
#gradient .middlepoint { top: -9px; position: absolute; display: none; cursor: default; }
#gradient .middlepoint.visible { display: block; }
#gradient .middlepoint.bottom { top: 27px; }
#gradient .middlepoint span { margin-left: -4px; width: 7px; height: 7px; background: url(../img/middlepoint.gif); display: block; }
#gradient .middlepoint.selected span { background-position: 0 -7px; }
#gradient_editor #stops { padding: 9px 9px 2px; font-size: 13px; }
#stops .disabled { color: #7f7f7f; }
#stops button { width: 89px; display: inline; }
#stops > div > div { width: 140px; display: inline-block; }
#stops span { width: 54px; margin-right: 4px; text-align: right; display: inline-block; }
#stops input[type="text"] { margin-right: 2px; }
#stop_color { width: 45px; height: 18px; margin-bottom: -5px; border: 1px solid #909090; display: inline-block; cursor: pointer; }
.disabled #stop_color { cursor: auto; }
.eyedropper { cursor: url(../img/eyedropper.gif) 0 15, auto; }
.colorcircle { cursor: url(../img/colorcircle.gif) 8 8, auto; }
.paint_bucket { cursor: url(../img/paint_bucket.gif) 13 14, auto; }
.resize { cursor: url(../img/resize.gif) 8 8, se-resize; }
.pot {
margin: 0 3px;
width: 40px;
height: 40px;
background: -moz-linear-gradient(top, #dbdbdb, #e1e1de 20%, #f8f8f3);
background: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), color-stop(50%, #e1e1de), to(#f8f8f3));
border: 2px solid #727272;
-moz-box-shadow: inset 0 2px 3px white, inset 0 -1px 2px #fffef8;
-webkit-box-shadow: inset 0 2px 3px white, inset 0 -1px 2px #fffef8;
box-shadow: inset 0 2px 3px white, inset 0 -1px 2px #fffef8;
-moz-border-radius: 40px;
-webkit-border-radius: 40px;
border-radius: 40px;
position: relative;
display: inline-block;
}
.pointer {
top: 50%;
left: 50%;
margin: -1.5px 0 0 -1.5px;
width: 50%;
-moz-transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
-moz-transform-origin: 1.5px 1.5px;
-webkit-transform-origin: 1.5px 1.5px;
transform-origin: 1.5px 1.5px;
position: absolute;
}
.dot {
height: 3px;
width: 3px;
background: #909090;
position: absolute;
}
.line {
margin-top: 1px;
height: 1px;
background: #909090;
}
.slider {
padding: 4px 0 2px 1px;
position: relative;
display: inline-block;
}
.slider .bar {
margin-top: 3px;
height: 3px;
background: -moz-linear-gradient(top, #adadad, #b2b2b2);
background: -webkit-gradient(linear, left top, left bottom, from(#adadad), to(#b2b2b2));
-moz-box-shadow: inset 0 1px 0 #929292;
-webkit-box-shadow: inset 0 1px 0 #929292;
box-shadow: inset 0 1px 0 #929292;
border: 1px solid #686868;
border-bottom-color: #aaa;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
.inactive .slider .bar {
background: -moz-linear-gradient(top, #bfbfbf, #d0d0d0);
background: -webkit-linear-gradient(top, #bfbfbf, #d0d0d0);
background: linear-gradient(top, #bfbfbf, #d0d0d0);
-moz-box-shadow: inset 0 1px 0 #bfbfbf;
-webkit-box-shadow: inset 0 1px 0 #bfbfbf;
box-shadow: inset 0 1px 0 #bfbfbf;
border-color: #aaa #aaa #cacaca;
}
.slider .arrow {
left: 0;
top: 3px;
position: absolute;
}
.slider .rear {
left: -3px;
top: 4px;
height: 5px;
width: 7px;
background: -moz-linear-gradient(top, #a7d4f6, #73bbf2, #b0e9fd);
background: -webkit-gradient(linear, left top, left bottom, from(#a7d4f6), color-stop(50%,#73bbf2), to(#b0e9fd));
border: 1px solid #787a96;
border-top-width: 0;
-moz-border-radius: 0 0 2px 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-box-shadow: 0 1px 0 rgba(0,0,0,.05);
position: relative;
}
.slider .spike {
left: -4px;
height: 4px;
width: 4px;
background: -moz-linear-gradient(-45deg, #e4f1fc, #88c4f2);
background: -webkit-gradient(linear, left top, right bottom, from(#e4f1fc), to(#88c4f2));
border: 1px solid #8d84ae;
-moz-transform-origin: 3px 7px;
-webkit-transform-origin: 3px 7px;
transform-origin: 3px 7px;
-moz-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
}
.inactive .slider .rear {
background: -moz-linear-gradient(#ECEDED, #DBDBDB, #EBEBEB);
background: -webkit-linear-gradient(#ECEDED, #DBDBDB, #EBEBEB);
background: linear-gradient(#ECEDED, #DBDBDB, #EBEBEB);
border-color: #7F7D7D;
}
.inactive .slider .spike {
background: -moz-linear-gradient(-45deg, #E1E1E1, white);
background: -webkit-linear-gradient(-45deg, #E1E1E1, white);
background: linear-gradient(-45deg, #E1E1E1, white);
border-color: #9E9E9E;
}
button {
width: 100%;
margin: 8px 0;
padding: 1px 0;
background: -moz-linear-gradient(top, #fcfcfc, #f4f4f4 40%, #e6e6e5 42%, #f5f5f5 75%, #fff);
background: -webkit-gradient(linear, left top, left bottom, from(#fcfcfc), color-stop(40%,#f4f4f4), color-stop(42%,#e6e6e5), color-stop(75%,#f5f5f5), to(#fff));
font-size: 12px;
border: 1px solid #7d7d7d;
-moz-border-radius: 17px;
-webkit-border-radius: 17px;
border-radius: 17px;
-moz-box-shadow: 0 1px 0 rgba(0,0,0,.2);
-webkit-box-shadow: 0 1px 0 rgba(0,0,0,.2);
box-shadow: 0 1px 0 rgba(0,0,0,.2);
display: block;
outline: none;
cursor: pointer;
}
button::-moz-focus-inner { border: 0; } /* firefox outline removed */
button:first-child { margin-top: 0; }
label[for] { cursor: pointer; }
#puff { width: 22px; height: 22px; background: url(../img/puff.png); position: absolute; display: block; z-index: 110; }
.clear { clear: both; }
================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Layer Styles</title>
<link rel="icon" type="image/png" href="favicon.png" />
<script type="text/javascript" src="js/modernizr-1.7.min.js"></script>
<link rel="stylesheet" href="css/index.css" type="text/css" />
</head>
<body>
<div id="arche">
<header>
<div id="logo">LS</div>
<div id="headline">
<h1>LayerStyles</h1>
<h3 class="tagline">just like your favorite graphics editor</h3>
<h3 class="tagline">but in your browser. And it creates CSS.</h3>
</div>
</header>
<section id="ready">
<a href="builder.html"><img class="hero" src="img/hero.png" width="556" height="393" alt="Layerstyles main interface" /></a>
</section>
<section id="not-ready">
<img class="hero" src="img/hero.png" width="556" height="393" alt="Layerstyles main interface" />
<div class="holder">
<div class="upper">
<h2>Unfortunately your browser doesn't support the following requirements:</h2>
<div class="features">
<span class="feature-js">Javascript enabled</span>
<span class="feature-json">Native JSON</span>
<span class="feature-cssgradients">CSS Background Gradients</span>
<span class="feature-borderradius">Border Radius</span>
<span class="feature-canvas">HTML5 Canvas</span>
<span class="feature-flexbox">HTML5 Flexbox</span>
<span class="feature-rgba">RGB Alpha-Channel</span>
<span class="feature-boxshadow">Box Shadows</span>
</div>
</div>
<div class="bottom">
<p>
Please update your browser.
</p>
</div>
</div>
</section>
<footer>
<p>LayerStyles is <em>Open Source</em> and on <a href="https://github.com/mrflix/LayerStyles">Github</a></p>
<p>made by <a href="http://www.felixniklas.de">Felix Niklas</a> © 2011 <em>follow me on mastodon:</em> <a href="https://mastodon.social/@mrflix">@mrflix</a>.</p>
</footer>
</div><!-- /arche -->
<script type="text/javascript" src="js/jquery-1.6.min.js"></script>
<script type="text/javascript" src="js/ui.js"></script>
<script type="text/javascript" src="js/zeroclipboard/ZeroClipboard.js"></script>
<script type="text/javascript" src="js/localization.js"></script>
<script type="text/javascript" src="js/color.js"></script>
<script type="text/javascript" src="js/numbers.js"></script>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/css.js"></script>
<script type="text/javascript" src="js/style.js"></script>
<script type="text/javascript" src="js/colorpicker.js"></script>
<script type="text/javascript" src="js/gradienteditor.js"></script>
<script type="text/javascript" src="js/codebox.js"></script>
<script type="text/javascript" src="js/universe.js"></script>
<script type="text/javascript" src="js/styleStore.js"></script>
</body>
</html>
================================================
FILE: js/application.js
================================================
/*!
* _ ________ _
* | | | ______| | |
* | | | | _ | |
* | | _____ ___ ___ _____ _____ | |______ _| |_ ___ ___ | | _____ _____
* | | | _ |\ \/ /| _ || __| |______ ||_ _|\ \/ / | | | _ || ___|
* | |_____ | |_| | / / | ___|| | ______| | | | / / | |___ | ___||___ |
* |_______||___,\|/___/ |_____||__| |________| |_| /___/ |_____||_____||_____|
*
* http://www.layerstyles.org
*
* Copyright (c) 2011 Felix Niklas
* This script is freely distributable under the terms of the MIT license.
*/
localStorage['version'] = "0.1";
var movePos = { x: 0, y: 0 }, bytes, reader;
var $body = $('body');
var $overlay = $('#overlay');
var $workspace = $('#workspace');
var dimensions = { width: $workspace.width(), height: $workspace.height() };
var $dialog = $('#dialog');
var $layerstyle = $('#layerstyle');
var $navElements = $('#nav ul li');
var $holderElements = $('#holder > div');
var $pots = $('.pot');
var potDimensions = {'height': 40, 'width': 40};
var $sliders = $('.slider'), shouldEase = false;
var $numericalInputs = $('input[type=text]', $dialog);
var $buttons = { 'ok': $('#ok'), 'cancel': $('#cancel'), 'newStyle': $('#new_style') };
var $layer = $('#layer');
var resizeArea = $('#resize');
var $backgroundLayer = $('#background_layer');//.css("height", dimensions.height);
var $parallelUniverse = $('#parallel_universe').attr({height: dimensions.height, width: dimensions.width});
var pu = $parallelUniverse.get(0).getContext('2d');
var $innerShadowUniverse = $('#innerShadow_universe').attr({height: dimensions.height, width: dimensions.width});
var iu = $innerShadowUniverse.get(0).getContext('2d');
var moveAreas = $('.moveable'), movingWindow;
var offset = { x: 0, y: 0 };
var $colorfields = $('.color_field');
var currentStyle, lang;
var background = {
background: [{
stops: [[255,255,255,1], [255,255,255,0]],
style: 'radial',
position: 'center',
angle: 90
},
{
stops: [[226, 226, 226], [171, 171, 171]],
style: 'linear',
angle: 90
}
]
};
// array compare function - thanks to David and Anentropic
// http://stackoverflow.com/questions/1773069/using-jquery-to-compare-two-arrays
// (sort removed and extended to deep comparison)
// syntax: $.compare(a, b);
jQuery.extend({
compare: function (b, a) {
if (a.length != b.length) { return false; }
for (var i = 0, l = a.length; i < l; i++) {
if (a[i] !== b[i]) {
if(typeof a[i] === 'object'){
return jQuery.compare(a[i],b[i]);
} else {
return false;
}
}
}
return true;
}
});
// Object.create implementation for older browsers
// by Ben Newman
if(Object.create === undefined){
Object.create = function( proto, props ) {
var ctor = function( ps ) {
if ( ps )
Object.defineProperties( this, ps );
};
ctor.prototype = proto;
return new ctor( props );
};
}
/*
things to store:
- styles, gradients and colors
- layerstyles version
- currentStyle
*/
var defaults = {
height: 300,
width: 300,
ratio: 1,
globalAngle: 90,
dropShadow: {
isActive: true,
color: [0,0,0],
opacity: 75,
angle: 90,
hasGlobalLight: false,
distance: 1,
blur: 5,
size: 0
},
innerShadow: {
isActive: false,
color: [255,255,255],
opacity: 100,
angle: 90,
hasGlobalLight: false,
distance: 1,
blur: 0,
size: 0,
isInset: true
},
background: {
isActive: true,
opacity: 100,
stops: [[252, 252, 252], 23, [[242, 242, 242], 12], 89, [191, 191, 191]],
isReverse: false,
style: 'linear',
angle: 90,
hasGlobalLight: false
},
border: {
isActive: true,
color: [0,0,0],
opacity: 100,
size: 1,
style: 'solid'
},
borderRadius: {
isActive: false,
radii: [[0, "px"],[0, "px"],[0, "px"],[0, "px"]],
isSelected: [true,true,true,true],
hasPercentage: [false, false, false, false]
}
};
var nav = {
$el: $layerstyle,
$pages: null,
width: null,
page: null,
prev: null,
speed: 0,
goTo: function(pageNr){
// parse Int
pageNr = pageNr*1;
localStorage["pageNr"] = pageNr;
if(pageNr === -1){
pageNr = this.prev; // go back
}
else {
pageNr--; // pages area 1,2,3 - but in the array they are 0,1,2
}
var goPage = this.$pages.eq(pageNr);
var currentPage = this.$pages.eq(this.page);
var direction = pageNr > this.page ? 1 : -1; // 1 = right, -1 = left
var offset = this.width;
this.$el.css('overflow', 'hidden');
currentPage
.animate({
'margin-left': -direction*offset+'px',
'opacity': 0
}, this.speed, function(){ nav.$pages.eq(nav.page).css('visibility', 'hidden'); });
goPage
.css({
'margin-left': direction*offset+'px',
'visibility': 'visible',
'opacity': 0
})
.animate({
'margin-left': 0,
'opacity': 1
}, this.speed, function(){ nav.$el.css('overflow', 'visible'); });
this.prev = this.page;
this.page = pageNr;
},
show: function(pageNr){
pageNr--;
$(this.$pages[pageNr]).css('visibility', 'visible');
this.page = pageNr;
},
init: function(){
this.width = this.$el.width();
this.$pages = $('> .window', this.$el);
this.show(1);
}
}
function moveWindow(event){
movingWindow.css({ top: event.pageY - movePos.y, left: event.pageX - movePos.x });
}
function resizeLayer(event, x, y){
var halfWidth, halfHeight, maxWidth, maxHeight;
halfWidth = parseInt(( x != null ? x/2 : event.pageX - dimensions.width/2 + offset.x), 10);
halfHeight = event != null && event.shiftKey ? halfWidth / currentStyle.ratio : parseInt(( y != null ? y/2 : event.pageY - dimensions.height/2 + offset.y), 10);
maxWidth = dimensions.width/2;
maxHeight = dimensions.height/2;
halfWidth = halfWidth < 8 ? 8 : halfWidth > maxWidth ? maxWidth : halfWidth;
halfHeight = halfHeight < 8 ? 8 : halfHeight > maxHeight ? maxHeight : halfHeight;
currentStyle.width = halfWidth*2;
currentStyle.height = halfHeight*2;
$layer.css({
'width': currentStyle.width,
'height': currentStyle.height,
'margin-top': -halfHeight,
'margin-left': -halfWidth
});
}
function showSlide(pos){
$navElements.removeClass('active');
$navElements.eq(pos).addClass('active');
$holderElements.removeClass('active').eq(pos).addClass('active');
}
function dragenter(e) {
e.stopPropagation();
e.preventDefault();
$body.addClass("dragging");
}
function dragleave(e) {
e.stopPropagation();
e.preventDefault();
$body.removeClass("dragging");
}
function dragover(e) {
e.stopPropagation();
e.preventDefault();
}
function drop(e) {
e.stopPropagation();
e.preventDefault();
dropPos = { x: e.pageX, y: e.pageY };
var dt = e.dataTransfer;
var files = dt.files;
for (var i = 0, l=files.length; i < l; i++) {
var data = files[i];
//bytes = new Stream(data);
reader = new FileReader();
reader.onload = function(e){
var img = new Image(),
$canvas = $("<canvas></canvas>"),
ctx = $canvas.get(0).getContext('2d');
img.src = e.target.result;
img.onload = function(){
$canvas.attr({
title: data.name,
width: img.width,
height: img.height
});
$canvas.css({ left: dropPos.x-img.width/2, top: dropPos.y-img.height/2, position: "absolute" });
$canvas.addClass("moveable");
ctx.drawImage(img, 0, 0);
$canvas.appendTo($workspace);
};
};
reader.readAsDataURL(data);
}
$body.removeClass("dragging");
}
function showPickArea(){
$body.addClass("pick");
// draw the parallel Universe for color picking
parallelUniverse.draw();
// redraw the parallelUniverse when the layer gets redrawn ("paint" event);
$(document).bind('paint', $.proxy( parallelUniverse, "draw" ));
$overlay.bind('mousedown', pick);
}
function hidePickArea(){
$body.removeClass("pick");
$(document).unbind('paint', $.proxy( parallelUniverse, "draw" ));
$overlay.unbind('mousedown');
}
function pick(event){
var pickedColor = pu.getImageData(event.pageX, event.pageY, 1, 1).data;
colorpicker.setHex(color.hexFromRgb(pickedColor));
colorpicker.update('hex');
}
function initialise() {
// include 'dataTransfer' to jquerys event object
jQuery.event.props.push('dataTransfer');
// set language
// not yet elaborated - whats the best solution to change all titles in the html?
// - create the html via js in the first place or select and change them all?
// - regex over the all textnodes?
lang = localization.en;
$navElements.click(function(){
var pos = $navElements.index(this);
localStorage["slidePos"] = pos;
showSlide(pos);
});
$numericalInputs.bind({
mousedown: function(e){ e.stopPropagation(); },
focus: function(e){ numbers.initNumberField(this, 'style'); },
keydown: numbers.restrictCharacters,
keyup: numbers.keyUp,
blur: numbers.validateInput
});
moveAreas.live('mousedown', function(event){
event.preventDefault();
movingWindow = $(this).hasClass("head") ? $(this).parents('#layerstyle') : $(this);
movingWindow.addClass("moving");
$(document).one('mouseup', function(){ movingWindow.removeClass("moving"); });
var myOffset = movingWindow.offset();
movePos = { x:event.pageX-myOffset.left, y:event.pageY-myOffset.top };
$(document).bind('mousemove.global', moveWindow);
});
resizeArea.bind({
mousedown: function(event){
event.preventDefault();
event.stopPropagation();
currentStyle.ratio = currentStyle.width/currentStyle.height;
$(document).bind('mousemove.global', resizeLayer);
$body.addClass("resize");
$(document).one('mouseup', function(){ $body.removeClass('resize'); });
var my_offset = $(this).offset();
offset = { x: 15-(event.pageX-my_offset.left), y: 15-(event.pageY-my_offset.top) };
},
click: function(event){ event.stopPropagation(); } // prevent bubbling
});
$(document).bind({
mousemove: function(e){ e.preventDefault(); },
mouseup: function(){ $(this).unbind('mousemove.global'); },
dragenter: dragenter,
dragleave: dragleave,
dragover: dragover,
drop: drop
});
$(window).bind({
resize: function(event){
dimensions = { width: $workspace.width(), height: $workspace.height() };
$parallelUniverse.attr({'width': dimensions.width, 'height': dimensions.height});
$innerShadowUniverse.attr({'width': dimensions.width, 'height': dimensions.height});
if (dimensions.width < currentStyle.width) { resizeLayer(null, dimensions.width, currentStyle.height); }
if (dimensions.height < currentStyle.height) { resizeLayer(null, currentStyle.width, dimensions.height); }
},
keydown: function(event){
if(event.altKey){
$body.addClass('alt');
$(this).one('keyup', function(){ $body.removeClass('alt'); });
}
}
});
$layer.dblclick(function(event){ $layerstyle.show(); });
$buttons.ok.click(function(){ $layerstyle.hide(); });
$buttons.cancel.click(function(){ $layerstyle.hide(); });
$buttons.newStyle.click( $.proxy( styleStore, "create" ) );
$('#infoButton').click(function(){ $body.removeClass('visited'); });
styleStore.init();
nav.init();
colorpicker.init();
gradienteditor.init();
codeBox.init();
style.init();
showSlide(localStorage["slidePos"] || 1);
nav.goTo(localStorage["pageNr"] || 1);
$(document)
.bind('paint', $.proxy( codeBox, "render" ))
.bind('paint', $.proxy( css, "render" ))
.trigger('styleChange')
.trigger('paint');
}
// isEven: (n % 2) == 0 -> true? even : odd
// GET THE BALL ROLLIN
$(document).ready(function(){
initialise();
});
================================================
FILE: js/codebox.js
================================================
var codeBox = {
options: {
visible: true,
height: 143
},
minHeight: 100,
init: function(){
if(localStorage["codeBoxOptions"]) this.options = JSON.parse(localStorage["codeBoxOptions"]);
this.$el = $('#codeBox');
this.$box = this.$el.find('code');
this.$body = this.$el.find('.body');
this.$copyCode = this.$el.find('#copyCode');
this.$dragger = this.$el.find('.dragger.y');
this.$codeBoxToggle = $('#codeBoxToggle');
this.$colorToggle = Object.create(toggle);
this.$colorToggle.init("colorSwitch", "hex", tools.options, $.proxy( this, "render" ));
this.location = window.location.href.slice(0, window.location.href.lastIndexOf("/"));
this.initClipboard();
this.$copyCode.add(this.$body).add(this.$box)
.bind('mousedown', function(e){ e.stopPropagation(); });
this.$codeBoxToggle.click( $.proxy( this, "toggle" ) );
this.$dragger.mousedown( $.proxy( this, "drag") );
this.updateView();
},
toggle: function(){
if(this.$el.height() === 0){
this.options.visible = true;
} else {
this.options.visible = false;
}
this.storeSettings();
this.updateView();
$(window).trigger('resize');
},
updateView: function(){
if(this.options.visible){
this.$el.height(this.options.height);
} else {
this.$el.height(0);
}
},
drag: function(event){
event.preventDefault();
var my_offset = $(event.target).offset();
offset = { y: event.pageY-my_offset.top };
this.$el.addClass("resizing");
this.resize(event);
$(document).one('mouseup', function(){ codeBox.$el.removeClass('resizing') } );
$(document).bind('mousemove.global', $.proxy( this, "resize") );
},
resize: function(event){
this.options.height = Math.max(this.minHeight, $(document).height() - event.pageY + offset.y);
this.$el.height(this.options.height);
$(window).trigger('resize');
this.storeSettings();
},
storeSettings: function(){
localStorage["codeBoxOptions"] = JSON.stringify(this.options);
},
/**
* @method initClipboard - a click on the button with the id 'copyCode' will copy 'this.$box.text()' into the clipboard
* @see http://code.google.com/p/zeroclipboard/wiki/Instructions
*/
initClipboard: function(){
ZeroClipboard.setMoviePath( this.location + '/js/zeroclipboard/ZeroClipboard.swf' );
this.clip = new ZeroClipboard.Client();
this.clip.addEventListener( 'onMouseDown', $.proxy( this, "copy" ) );
this.clip.setHandCursor(true);
var flash = this.clip.getHTML(this.$copyCode.width(), this.$copyCode.height());
this.$copyCode.append(flash);
},
copy: function(){
var text = this.code.replace(/<br>/g, "\n").replace(/ /g, "");
this.clip.setText(text);
},
tabs: function(count){
var tabString = "",
tabs = count || this.options.tabs;
for(;tabs--;){
tabString += " ";
}
return tabString;
},
render: function(){
var borderRadiusObject;
this.code = "";
// add border
this.code += currentStyle.border.isActive ? "border: " + css.border(currentStyle) + ";<br>" : "";
// add border-radius
if(currentStyle.borderRadius.isActive){
borderRadiusObject = css.borderRadius(currentStyle);
for(var key in borderRadiusObject){
var radius = borderRadiusObject[key];
if(radius !== 0){
this.code += key + ": " + radius + ";<br>";
}
}
}
// add gradient
if(currentStyle.background.isActive){
this.code += "background-image: " + css.drawGradient(currentStyle) + ";<br>";
}
// add dropShadow and innerShadow
if(currentStyle.dropShadow.isActive || currentStyle.innerShadow.isActive){
this.code += "box-shadow: " + css.boxShadow(currentStyle) + ";<br>";
}
this.$box.html(this.code);
}
};
================================================
FILE: js/color.js
================================================
var color = {
hsbFromRgb: function(rgb) {
r = rgb[0]/255, g = rgb[1]/255, b = rgb[2]/255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, v = max;
var d = max - min;
s = max === 0 ? 0 : d / max;
if(max === min){
h = 0;
}else{
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [Math.round(h * 360), Math.round(s * 100), Math.round(v * 100)];
},
rgbFromHsb: function(hsv) {
var r, g, b;
h = hsv[0]/360; s = hsv[1]/100; v = hsv[2]/100;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch(i % 6){
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
},
rgbFromHex: function(hex){
if(hex.length === 3){
return [
parseInt(hex.substring(0,1)+hex.substring(0,1), 16),
parseInt(hex.substring(1,2)+hex.substring(1,2), 16),
parseInt(hex.substring(2,3)+hex.substring(2,3), 16)
]
} else {
return [
parseInt(hex.substring(0,2), 16),
parseInt(hex.substring(2,4), 16),
parseInt(hex.substring(4,6), 16)
]
}
},
hexFromRgb: function(rgb){
var hexcode = this.toHex(rgb[0])+this.toHex(rgb[1])+this.toHex(rgb[2]),
parts = hexcode.split("");
// "000" instead of "000000"
return (parts[0]===parts[1]) && (parts[2]===parts[3]) && (parts[4]==parts[5]) ? parts[0]+parts[2]+parts[4] : hexcode;
},
toHex: function(n) {
if(n === 0) { return '00'; }
n = parseInt(n, 10);
if (n === 0 || isNaN(n)) { return "00"; }
return "0123456789abcdef".charAt((n-n%16)/16) + "0123456789abcdef".charAt(n%16);
}
};
================================================
FILE: js/colorpicker.js
================================================
/*
* LayerStyles
* http://www.layerstyles.org
*
* Copyright (c) 2011 Felix Niklas
* This script is freely distributable under the terms of the MIT license.
*/
var colorpicker = {
open: false,
currentColor: "000000", // hex
callback: null,
thisArg: null,
swatches: [
{'title': 'White', 'hex': 'ffffff'},
{'title': '10% Gray', 'hex': 'e5e5e5'},
{'title': '20% Gray', 'hex': 'cccccc'},
{'title': '30% Gray', 'hex': 'b3b3b3'},
{'title': '40% Gray', 'hex': '999999'},
{'title': '50% Gray', 'hex': '808080'},
{'title': '60% Gray', 'hex': '666666'},
{'title': '70% Gray', 'hex': '4d4d4d'},
{'title': '80% Gray', 'hex': '333333'},
{'title': '90% Gray', 'hex': '1a1a1a'},
{'title': 'Black', 'hex': '000000'}
],
$selectedInput: null,
colorHistory: [],
pointerPos: { 'x': 0, 'y': 0 },
hsb: { h: 0, s: 0, b: 0 },
rgb: { r: 0, g: 0, b: 0 },
hex: '000000',
mode: 'hsb_b',
max: 0, // the maximum input value
ratio: 0, // the ratio for the slider: its 0.7111 (hue), ~1 (rgb) or 2.56 (saturation/brightness)
offset: 0, // the offset relative to the document will be stored in here to calculate mouse-dragging
pick: function(rgbArray, callback, thisArg) {
showPickArea();
this.callback = callback;
this.thisArg = thisArg;
// set rgb
this.setRgb(parseInt(rgbArray[0],10),parseInt(rgbArray[1],10),parseInt(rgbArray[2],10));
// update
this.update('rgb_r');
// set currentColor
this.setCurrentColor();
// show it
nav.goTo(3);
},
setCurrentColor: function(hex) {
this.currentColor = hex || this.hex;
this.$currentColor.css('background', '#'+this.currentColor);
},
pickCurrentColor: function(){
this.setHex(this.currentColor);
this.update('hex');
},
clickHex: function(){
this.$hex.focus();
},
update: function(customMode) {
var updateMode = customMode || this.mode;
switch(updateMode){
case 'hsb_h': case 'hsb_s': case 'hsb_b':
this.getHsb();
this.hsbToRgb();
this.rgbToHex();
break;
case 'rgb_r': case 'rgb_g': case 'rgb_b':
this.getRgb();
this.rgbToHsb();
this.rgbToHex();
break;
case 'hex':
this.getHex();
this.hexToRgb();
this.rgbToHsb();
break;
}
this.paintField();
this.paintSlider();
this.setNewColor();
this.moveSlider(this.$selectedInput.val()*this.ratio);
if(this.callback) this.callback.call(this.thisArg, color.rgbFromHex(this.hex));
},
paintField: function() {
var xGradient, yGradient;
this.cf.save();
this.cf.clearRect(0,0,256,256);
xGradient = this.cf.createLinearGradient(0, 0, 0, 256);
yGradient = this.cf.createLinearGradient(0, 0, 256, 0);
switch (this.mode) {
case 'hsb_h': // rainbow
var hue = color.rgbFromHsb([this.hsb.h, 100, 100]);
yGradient.addColorStop(0, 'white');
yGradient.addColorStop(1, 'rgb('+hue[0]+','+hue[1]+','+hue[2]+')');
xGradient.addColorStop(0, 'transparent');
xGradient.addColorStop(1, 'black');
break;
case 'hsb_s': // rainbow
yGradient.addColorStop(0, 'rgb(255,0,0)');
yGradient.addColorStop(1/6, 'rgb(255,255,0)');
yGradient.addColorStop(2/6, 'rgb(0,255,0)');
yGradient.addColorStop(3/6, 'rgb(0,255,255)');
yGradient.addColorStop(4/6, 'rgb(0,0,255)');
yGradient.addColorStop(5/6, 'rgb(255,0,255)');
yGradient.addColorStop(1, 'rgb(255,0,0)');
xGradient.addColorStop(0, 'rgba(0,0,0,'+(1-this.hsb.s/100)+')' );
xGradient.addColorStop(1, 'black' );
break;
case 'hsb_b': // rainbow from saturated to unsaturated
var grey = parseInt(this.hsb.b*2.56, 10);
yGradient.addColorStop(0, 'rgb(255,0,0)');
yGradient.addColorStop(1/6, 'rgb(255,255,0)');
yGradient.addColorStop(2/6, 'rgb(0,255,0)');
yGradient.addColorStop(3/6, 'rgb(0,255,255)');
yGradient.addColorStop(4/6, 'rgb(0,0,255)');
yGradient.addColorStop(5/6, 'rgb(255,0,255)');
yGradient.addColorStop(1, 'rgb(255,0,0)');
xGradient.addColorStop(0, 'rgba('+grey+','+grey+','+grey+','+(1-this.hsb.b/100)+')');
xGradient.addColorStop(1, 'rgb('+grey+','+grey+','+grey+')');
break;
case 'rgb_r':
this.cf.globalCompositeOperation = 'lighter';
xGradient.addColorStop(0, 'rgb('+this.rgb.r+',255,0)');
xGradient.addColorStop(1, 'rgb('+this.rgb.r+',0,0)');
yGradient.addColorStop(0, 'rgb('+this.rgb.r+',0,0)');
yGradient.addColorStop(1, 'rgb('+this.rgb.r+',0,255)');
break;
case 'rgb_g':
this.cf.globalCompositeOperation = 'lighter';
xGradient.addColorStop(0, 'rgb(255,'+this.rgb.g+',0)');
xGradient.addColorStop(1, 'rgb(0,'+this.rgb.g+',0)');
yGradient.addColorStop(0, 'rgb(0,'+this.rgb.g+',0)');
yGradient.addColorStop(1, 'rgb(1,'+this.rgb.g+',255)');
break;
case 'rgb_b':
this.cf.globalCompositeOperation = 'lighter';
xGradient.addColorStop(0, 'rgb(0,255,'+this.rgb.b+')');
xGradient.addColorStop(1, 'rgb(0,0,'+this.rgb.b+')');
yGradient.addColorStop(0, 'rgb(0,0,'+this.rgb.b+')');
yGradient.addColorStop(1, 'rgb(255,0,'+this.rgb.b+')');
break;
}
this.cf.beginPath();
this.cf.rect(0, 0, 256, 256);
this.cf.closePath();
this.cf.fillStyle = yGradient;
this.cf.fill();
this.cf.beginPath();
this.cf.rect(0, 0, 256, 256);
this.cf.closePath();
this.cf.fillStyle = xGradient;
this.cf.fill();
this.cf.restore();
this.movePointer();
},
startPointer: function(event) {
this.offset = this.$circleField.offset();
this.calculatePointer(event);
$(document).bind('mousemove.global', jQuery.proxy(this, "calculatePointer"));
},
calculatePointer: function(event) {
event.preventDefault();
this.pointerPos.x = Math.max(0, Math.min(256, event.pageX-this.offset.left));
this.pointerPos.y = Math.max(0, Math.min(256, event.pageY-this.offset.top));
switch(this.mode){
case 'hsb_h':
this.$hsb_s.val(parseInt(this.pointerPos.x/2.56, 10));
this.$hsb_b.val(100-parseInt(this.pointerPos.y/2.56, 10));
break;
case 'hsb_s':
this.$hsb_h.val(parseInt(this.pointerPos.x/0.71111, 10));
this.$hsb_b.val(100-parseInt(this.pointerPos.y/2.56, 10));
break;
case 'hsb_b':
this.$hsb_h.val(parseInt(this.pointerPos.x/0.71111, 10));
this.$hsb_s.val(100-parseInt(this.pointerPos.y/2.56, 10));
break;
case 'rgb_r':
this.$rgb_b.val(parseInt(this.pointerPos.x/1.003921, 10));
this.$rgb_g.val(255-parseInt(this.pointerPos.y/1.003921, 10));
break;
case 'rgb_g':
this.$rgb_b.val(parseInt(this.pointerPos.x/1.003921, 10));
this.$rgb_r.val(255-parseInt(this.pointerPos.y/1.003921, 10));
break;
case 'rgb_b':
this.$rgb_r.val(parseInt(this.pointerPos.x/1.003921, 10));
this.$rgb_g.val(255-parseInt(this.pointerPos.y/1.003921, 10));
break;
}
this.movePointer();
this.update();
},
movePointer: function(x, y) {
this.pointerPos.x = x >= 0 ? x : this.pointerPos.x;
this.pointerPos.y = y >= 0 ? y : this.pointerPos.y;
this.cc.clearRect(0,0,256,256);
// limit x and y to 0-255 cause we need +1 (=256) space to detect the underlaying color
var detectX = Math.min(255, this.pointerPos.x),
detectY = Math.min(255, this.pointerPos.y);
var background = this.cf.getImageData(detectX, detectY, 1, 1).data;
// check if the underlying color is dark or light and set the circle color according to that
// -> white circle if the underlying color is dark (treshhold of 128 - where 256 is white) - otherwise black
this.cc.strokeStyle = ((background[0]+background[1]+background[2])/3) < 128 ? 'white' : 'black';
this.cc.beginPath();
this.cc.arc(detectX + 0.5, detectY + 0.5, 5, 0, Math.PI*2, true);
this.cc.closePath();
this.cc.stroke();
},
drawPointer: function() {
var posX = 0,
posY = 0;
switch(this.mode){
case 'hsb_h':
posX = this.hsb.s*2.56;
posY = (100-this.hsb.b)*2.56;
break;
case 'hsb_s':
posX = this.hsb.h*0.71111;
posY = (100-this.hsb.b)*2.56;
break;
case 'hsb_b':
posX = this.hsb.h*0.71111;
posY = (100-this.hsb.s)*2.56;
break;
case 'rgb_r':
posX = this.rgb.b*1.003921;
posY = (255-this.rgb.g)*1.003921;
break;
case 'rgb_g':
posX = this.rgb.b*1.003921;
posY = (255-this.rgb.r)*1.003921;
break;
case 'rgb_b':
posX = this.rgb.r*1.003921;
posY = (255-this.rgb.g)*1.003921;
break;
}
this.movePointer(parseInt(posX, 10), parseInt(posY, 10));
},
paintSlider: function() {
var gradient = this.cs.createLinearGradient(0, 0, 0, 256);
this.cs.clearRect(0,0,19,256);
switch (this.mode) {
case 'hsb_h': // rainbow
gradient.addColorStop(0, 'rgb(255,0,0)');
gradient.addColorStop(1/6, 'rgb(255,0,255)');
gradient.addColorStop(2/6, 'rgb(0,0,255)');
gradient.addColorStop(3/6, 'rgb(0,255,255)');
gradient.addColorStop(4/6, 'rgb(0,255,0)');
gradient.addColorStop(5/6, 'rgb(255,255,0)');
gradient.addColorStop(1, 'rgb(255,0,0)');
break;
case 'hsb_s': // max saturation to unsaturated
var brightness = this.hsb.b;
if(brightness <= 33) brightness = 33;
var saturated = color.rgbFromHsb([this.hsb.h, 100, brightness]);
var unsaturated = color.rgbFromHsb([this.hsb.h, 0, brightness]);
gradient.addColorStop(0, 'rgb('+saturated[0]+','+saturated[1]+','+saturated[2]+')');
gradient.addColorStop(1, 'rgb('+unsaturated[0]+','+unsaturated[1]+','+unsaturated[2]+')');
break;
case 'hsb_b': // max brightness to black
var brightest = color.rgbFromHsb([this.hsb.h, this.hsb.s, 100]);
gradient.addColorStop(0, 'rgb('+brightest[0]+','+brightest[1]+','+brightest[2]+')');
gradient.addColorStop(1, 'black');
break;
case 'rgb_r':
gradient.addColorStop(0, 'rgb(255,'+this.rgb.g+','+this.rgb.b+')');
gradient.addColorStop(1, 'rgb(0,'+this.rgb.g+','+this.rgb.b+')');
break;
case 'rgb_g':
gradient.addColorStop(0, 'rgb('+this.rgb.r+',255,'+this.rgb.b+')');
gradient.addColorStop(1, 'rgb('+this.rgb.r+',0,'+this.rgb.b+')');
break;
case 'rgb_b':
gradient.addColorStop(0, 'rgb('+this.rgb.r+','+this.rgb.g+',255)');
gradient.addColorStop(1, 'rgb('+this.rgb.r+','+this.rgb.g+',0)');
break;
}
this.cs.beginPath();
this.cs.rect(0, 0, 19, 256);
this.cs.closePath();
this.cs.fillStyle = gradient;
this.cs.fill();
},
startSlider: function(event) {
this.offset = this.$slideArea.offset();
this.slide(event);
$(document).bind('mousemove.global', jQuery.proxy(this, "slide"));
},
slide: function(event) {
event.preventDefault();
var relativePosition = event.pageY - this.offset.top;
if(relativePosition < 0) relativePosition = 0;
if(relativePosition > 256) relativePosition = 256;
// invert the value because the browsers coordination system has its origin at the top but the slider has its origin at the bottom
relativePosition = 256 - relativePosition;
this.moveSlider(relativePosition);
this.$selectedInput.val(parseInt(relativePosition/this.ratio, 10));
this.update();
},
moveSlider: function(position) {
this.$slider.css({'top':(256-position)+'px'});
},
getHsb: function() {
this.hsb.h = this.$hsb_h.val();
this.hsb.s = this.$hsb_s.val();
this.hsb.b = this.$hsb_b.val();
},
getRgb: function() {
this.rgb.r = this.$rgb_r.val();
this.rgb.g = this.$rgb_g.val();
this.rgb.b = this.$rgb_b.val();
},
getHex: function() {
var hex = this.$hex.val();
var missingLength = 6 - hex.length;
if(missingLength === 3){
var parts = hex.split("");
hex = parts[0]+parts[0]+parts[1]+parts[1]+parts[2]+parts[2];
} else {
for(var i = 0; i<missingLength; i++){
hex = "0" + hex;
}
}
this.hex = hex;
},
setHsb: function() {
this.$hsb_h.val(this.hsb.h);
this.$hsb_s.val(this.hsb.s);
this.$hsb_b.val(this.hsb.b);
},
setRgb: function(r,g,b) {
this.$rgb_r.val(r != null ? r : this.rgb.r);
this.$rgb_g.val(g != null ? g : this.rgb.g);
this.$rgb_b.val(b != null ? b : this.rgb.b);
},
setHex: function(hex) {
var hexcode = hex || this.hex,
parts = hexcode.split("");
// "000" instead of "000000"
hexcode = (parts[0]===parts[1]) && (parts[2]===parts[3]) && (parts[4]==parts[5]) ? parts[0]+parts[2]+parts[4] : hexcode;
this.$hex.val(hexcode);
},
hsbToRgb: function() {
var rgb = color.rgbFromHsb([this.hsb.h, this.hsb.s, this.hsb.b]);
this.rgb.r = rgb[0];
this.rgb.g = rgb[1];
this.rgb.b = rgb[2];
this.setRgb();
},
rgbToHex: function(){
this.hex = color.hexFromRgb([this.rgb.r, this.rgb.g, this.rgb.b]);
this.setHex();
},
hexToRgb: function(){
var rgb = color.rgbFromHex(this.hex);
this.rgb.r = rgb[0];
this.rgb.g = rgb[1];
this.rgb.b = rgb[2];
this.setRgb();
},
setNewColor: function() {
this.$newColor.css('background', '#'+this.hex);
},
rgbToHsb: function() {
var hsb = color.hsbFromRgb([this.rgb.r, this.rgb.g, this.rgb.b]);
this.hsb.h = hsb[0];
this.hsb.s = hsb[1];
this.hsb.b = hsb[2];
this.setHsb();
},
addSwatch: function(title, hex) {
return $('<span class="swatch" />')
.attr({'title': title, 'data-hex': hex})
.css({'background': '#'+hex})
.bind('click', {self: this}, this.handleSwatch);
},
handleSwatch: function(e){
e.stopPropagation();
var self = e.data.self;
// if alt is pressed while clicking: remove swatch
if(e.altKey){
// find out the swatches position in the swatch array
var position = 0;
var family = $(this).parent().children();
for(var i = 0, length = family.length; i<length; i++){
if(this===family[i]){ position = i; }
}
// slice out the swatch from the swatch array (method by John Resig)
var rest = self.swatches.slice(position + 1);
self.swatches.length = position;
self.swatches.push.apply(self.swatches, rest);
localStorage["swatches"] = JSON.stringify(self.swatches);
$(this).remove();
}
// else get that swatches color
else {
var hex = $(this).attr('data-hex');
self.setHex(hex);
self.update('hex');
}
},
okAction: function(){
this.close("ok");
},
cancelAction: function(){
this.close("cancel");
},
close: function(mode){
var rgb;
switch(mode){
case "ok":
this.setCurrentColor();
this.colorHistory.push(this.currentColor);
rgb = color.rgbFromHex(this.hex);
break;
case "cancel":
rgb = color.rgbFromHex(this.currentColor);
break;
}
if(this.callback) this.callback.call(this.thisArg, rgb);
this.callback = null;
this.open = false;
hidePickArea();
nav.goTo(-1);
},
newSwatch: function(event){
var self = event.data.self;
var title = prompt(lang.ColorSwatchName,"Swatch "+self.swatches.length);
if(title){
self.$swatchHolder.append(self.addSwatch(title, self.hex));
self.swatches.push({'title': title, 'hex': self.hex});
localStorage["swatches"] = JSON.stringify(self.swatches);
}
},
drawSwatches: function(){
var swatches = $('<div/>');
for(var i = 0, length = this.swatches.length; i<length; i++){
swatches.append( this.addSwatch(this.swatches[i].title, this.swatches[i].hex) );
}
this.$swatchHolder.append(swatches);
},
selectInput: function(pos){
this.mode = this.$radioInputs.eq(pos).val();
this.$selectedInput = this.$textInputs.eq(pos);
this.$selectedInput.focus();
this.max = this.$selectedInput.attr('data-max');
this.ratio = 256/this.max;
this.moveSlider(this.$selectedInput.val()*this.ratio);
this.drawPointer();
},
findCheckedInput: function(){
for (var i = 0; i<6; i++) {
if (this.$radioInputs.eq(i).attr('checked')) {
this.selectInput(i);
}
}
},
clickAll: function(event) {
var self = event.data.self;
var $currentRadio = $('input[type=radio]', this);
var $currentText = $('input[type=text]', this);
var clickTargetType = $(event.target).attr('type');
switch(clickTargetType){
case "radio":
$currentText.focus();
self.mode = $currentRadio.val();
self.max = $currentText.attr('data-max');
self.ratio = 256/self.max;
self.$selectedInput = $currentText;
self.update();
self.moveSlider($currentText.val()*self.ratio);
self.drawPointer();
break;
case "text": self.update(); break;
case "number": self.update(); break;
default:
$currentRadio.attr('checked', 'ckecked');
$currentText.focus();
self.mode = $currentRadio.val();
self.max = $currentText.attr('data-max');
self.update();
}
},
init: function() {
this.$element = $('#colorpicker');
this.$textHolder = this.$element.find('li');
this.$hexHolder = $('#hex_holder');
this.$swatchHolder = $('#swatches');
this.$currentColor = $('#current_color');
this.$newColor = $('#new_color');
this.$textInputs = this.$element.find('li input[type=text]');
this.$radioInputs = this.$element.find('li input[type=radio]');
this.$hsb_h = $('#hsb_h');
this.$hsb_s = $('#hsb_s');
this.$hsb_b = $('#hsb_b');
this.$rgb_r = $('#rgb_r');
this.$rgb_g = $('#rgb_g');
this.$rgb_b = $('#rgb_b');
this.$hex = $('#hex');
this.$button_ok = $('#color_ok');
this.$button_cancel = $('#color_cancel');
this.$circleField = $('#circle');
this.$slideArea = $('#color_slider');
this.$slider = this.$slideArea.find('> div');
this.cf = $('#field').get(0).getContext('2d');
this.cc = $('#circle').get(0).getContext('2d');
this.cs = this.$slideArea.find('canvas').get(0).getContext('2d');
if(localStorage["swatches"]) this.swatches = JSON.parse(localStorage["swatches"]);
this.$currentColor.click( jQuery.proxy(this, "pickCurrentColor") );
this.$button_ok.click( jQuery.proxy(this, "okAction") );
this.$button_cancel.click( jQuery.proxy(this, "cancelAction") );
this.$circleField.mousedown( jQuery.proxy(this, "startPointer") );
this.$slideArea.mousedown( jQuery.proxy(this, "startSlider") );
this.$textHolder.bind('click', {self: this}, this.clickAll);
this.$hexHolder.click( jQuery.proxy(this, "clickHex") );
this.$hex.bind({
focus: function(){ numbers.initHexField(this, 'color'); },
keydown: numbers.restrictCharacters,
keyup: numbers.keyUp
});
this.$textInputs.bind({
focus: function(){ numbers.initNumberField(this, 'color'); },
keydown: numbers.restrictCharacters,
keyup: numbers.keyUp,
blur: numbers.validateInput
});
this.$swatchHolder.bind('click', {self: this}, this.newSwatch);
// find initial checked input
this.findCheckedInput();
// draw swatches
this.drawSwatches();
this.update();
}
};
================================================
FILE: js/css.js
================================================
var css = {
colors: {
'rgb(0,0,0)': "black",
'rgb(255,255,255)': "white"
},
gradientDirections: {
315: "to bottom right",
270: "to bottom",
225: "to bottom left",
180: "to left",
135: "to top left",
90: "to top",
45: "to top right",
0: "to right"
},
/**
* @method cssGradient
* @param gradient {object}
* @return {array} decoded color stops: rgb strings
* @example cssGradient([0,0,0], 10, [255,255,255]) returns "-moz-linear-gradient(top, 'rgb(0,0,0)', 'rgb(25,25,25) 10%', 'rgb(255,255,255)')"
*/
cssGradient: function(stops, angle, style){
var tempStops, shape = "", cssString = "", pos;
switch(style){
case "linear": case "reflected":
tempStops = style === "reflected" ? tools.reflectStops(stops) : stops;
if (this.gradientDirections[angle]) {
pos = this.gradientDirections[angle];
} else {
pos = angle+"deg";
}
if(pos == "to bottom"){
cssString = 'linear-gradient('+ tools.decodeStops(tempStops).join(", ") +')';
} else {
cssString = 'linear-gradient('+ pos +', '+ tools.decodeStops(tempStops).join(", ") +')';
}
break;
case "contain":
cssString = 'radial-gradient(center center, '+shape+'contain, '+ tools.decodeStops(stops).join(", ") +')';
break;
case "cover":
cssString = 'radial-gradient(center center, '+shape+'cover, '+ tools.decodeStops(stops).join(", ") +')';
break;
}
return cssString;
},
drawGradient: function(style){
var cssString = "",
model = style.background,
tempAngle, tempOpacity, tempStops;
if(model.isActive) {
tempAngle = model.angle+180;
if(tempAngle >= 360) tempAngle -= 360;
tempOpacity = model.opacity;
if(tempOpacity != 100){
tempOpacity = model.opacity/100;
}
if(!model.translucidStops) model.translucidStops = $.extend(true, [], model.stops);
// inject opacity into the rgb values or slice off the injection if opacity is 100
for(var i=0, l=model.translucidStops.length; i<l; i++){
switch(model.stops[i].length){
case 2: // [[255,255,255], 45]
if(tempOpacity === 100){
model.translucidStops[i][0] = model.translucidStops[i][0].slice(0,3);
} else {
model.translucidStops[i][0][3] = tempOpacity;
}
break;
case 3: case 4: // [255,255,255] or [255,255,255,0.5]
if(tempOpacity === 100){
model.translucidStops[i] = model.translucidStops[i].slice(0,3);
} else {
model.translucidStops[i][3] = tempOpacity;
}
break;
}
}
tempStops = model.translucidStops.slice(0); // no deep copy!
if(model.hasGlobalLight) tempAngle = style.globalAngle;
if(model.isReverse) tempStops = tools.reverseStops(tempStops);
cssString = this.cssGradient( tempStops, tempAngle, model.style );
}
return cssString;
},
boxShadow: function(style){
var cssString = "", radiants, dropColor, tempSize, tempX, tempY, tempBlur,
shadows = ["dropShadow", "innerShadow"];
for(var i=0; i<shadows.length; i++){
var model = style[shadows[i]];
if(model.isActive){
if(cssString != "") cssString += ", ";
if(model.hasGlobalLight) model.angle = style.globalAngle;
radiants = (Math.PI / 180) * model.angle;
model.dropX = Math.round(-model.distance * Math.cos(radiants));
model.dropY = Math.round(model.distance * Math.sin(radiants));
tempX = model.dropX === 0 ? "0 " : model.dropX + "px ";
tempY = model.dropY === 0 ? "0 " : model.dropY + "px ";
tempBlur = model.blur === 0 ? "0 " : model.blur + "px ";
tempSize = model.size === 0 ? "" : model.size+"px ";
if(model.opacity != 100){
dropColor = model.color.slice(0);
dropColor.push(model.opacity/100);
} else {
dropColor = model.color;
}
if(model.isInset) cssString += "inset ";
cssString += tempX + tempY + tempBlur + tempSize + tools.toColor(dropColor);
}
}
return cssString;
},
border: function(style){
var cssString = "",
dropColor, model = style.border;
if(model.isActive){
if(model.opacity != 100){
dropColor = model.color.slice(0);
dropColor.push(model.opacity/100);
} else {
dropColor = model.color;
}
cssString += model.size+'px '+model.style+' '+tools.toColor(dropColor);
}
return cssString;
},
borderRadius: function(style){
var cssObject = { "border-radius": 0 },
model = style.borderRadius;
if(model.isActive){
var radii = [];
for(var i=0; i<4; i++){
var radius = model.radii[i]; // [pos, unit]
if(radius[0] !== 0){
radii[i] = radius[0] + radius[1];
} else {
radii[i] = 0;
}
}
// check if radii are the same
if( radii[0] === radii[1] &&
radii[1] === radii[2] &&
radii[2] === radii[3] &&
radii[3] === radii[0] ){
cssObject["border-radius"] = radii[0];
} else {
var topLeft = radii[0],
topRight = radii[1],
bottomRight = radii[2],
bottomLeft = radii[3];
if(topRight === bottomLeft){
if(topLeft === bottomRight){
cssObject["border-radius"] = topLeft+" "+topRight;
} else {
cssObject["border-radius"] = topLeft+" "+topRight+" "+bottomRight;
}
} else {
delete cssObject["border-radius"];
if(topLeft !== 0){
$.extend( cssObject, {'border-top-left-radius': topLeft} );
}
if(topRight !== 0){
$.extend( cssObject, {'border-top-right-radius': topRight} );
}
if(bottomRight !== 0){
$.extend( cssObject, {'border-bottom-right-radius': bottomRight} );
}
if(bottomLeft !== 0){
$.extend( cssObject, {'border-bottom-left-radius': bottomLeft} );
}
}
}
} // if borderRadius active
return cssObject;
},
displayCss: function(style){
var cssObj = {
'background': this.drawGradient(style),
'border': this.border(style),
'box-shadow': this.boxShadow(style)
};
$.extend(true, cssObj, this.borderRadius(style));
return cssObj;
},
render: function(){
$layer.css( this.displayCss(currentStyle) );
}
};
================================================
FILE: js/gradienteditor.js
================================================
var gradienteditor = {
callback: null,
thisArg: null,
changed: false,
puff: null,
gradientDimensions: null,
gradientOffset: null,
prevStops: null,
currentGradient: null,
currentPick: null,
currentStopColor: null,
currentPosition: null,
currentColorField: null,
tempStops: null,
gradients: [
{'name': "Black and White", 'stops': [[255, 255, 255], [0, 0, 0]] },
{'name': "Plain Gray", 'stops': [[252, 252, 252], 23, [[242, 242, 242], 12], 89, [191, 191, 191]] },
{'name': "Be Water", 'stops': [[209, 237, 233], 23, [[177, 228, 220], 12], 89, [0, 191, 162]] },
{'name': "Rainbow", 'stops': [[255, 0, 0], [[255, 0, 255], 15], [[0, 0, 255], 33], [[0, 255, 255], 49], [[0, 255, 0], 67], [[255, 255, 0], 84], [255, 0, 0]] },
{'name': "Teal, Magenta, Yellow", 'stops': [[255, 185, 13], [[204, 0, 69], 50], [0, 153, 128]] },
{'name': "Peach", 'stops': [[242, 171, 43], [225, 123, 25]] },
{'name': "Yellow, Orange", 'stops': [[255, 238, 88], [[252, 199, 54], 28], [[241, 141, 70], 67], [[233, 93, 59], 89], [228, 42, 50]] },
{'name': "PS i love you", 'stops': [[22,127,232],[0,60,123]] },
{'name': "Vista", 'stops': [[116,116,116], [[109,109,109], 50], [[126,126,126], 50], [133,133,133]]}
],
edit: function(stops, callback, thisArg){
var name = lang.Custom;
this.callback = callback;
this.thisArg = thisArg;
this.prevStops = stops;
// if the gradient is known, display its name
for(var i=0, l=this.gradients.length; i<l; i++){
if(this.gradients[i].stops === stops){
name = this.gradients[i].name;
}
}
// if the gradient is new, set changed to true to allow it to be stored
if(name === lang.Custom) this.changed = true;
this.setGradient({ name: name, stops: stops });
nav.goTo(2);
},
picker: {
init: function(color, position){
this.color = color;
this.position = position;
this.$el = this.create();
this.$colorField = this.$el.find('.color_field');
return this.$el;
},
create: function(){
$('<div class="picker bottom" />')
.css({ 'left': position+'%' })
.bind({
mousedown: $.proxy( this, "select" ),
dblclick: $.proxy( this, "pick" )
})
.append($('<div class="arrow" />'))
.append($('<div class="box" />')
.append($('<div class="color_field" />').css({ 'background': tools.toColor(color) }))
);
},
select: function(){
// fire "unselect" event
// show middlepoints
// add active class to this one
// show color and position below
// add pick event listener to the colorField
// add event listener to the input field to update the position
// add event listener on "unselect" to unselect
},
blur: function(){
// remove active class
// hide middle points
// remove "unselect" listener
},
pick: function(){
colorpicker.pick(this.color, this.updateColor, this);
},
updateColor: function(newColor){
var colorString = color.toColor(newColor);
this.color = newColor;
this.$stopColor.css("background", colorString);
this.$colorField.css("background", colorString);
// add color to stops
},
updatePosition: function(newPos){
this.position = newPos;
// update position at stops
}
},
middlepoint: {
threshhold: 5,
position: null,
percentage: null,
init: function(position, percentage){
this.position = position;
this.percentage = percentage;
this.$el = this.create();
return this.$el;
},
create: function(){
return $('<span class="middlepoint bottom"><span /></span>')
.attr({
'data-percentage': this.percentage,
})
.css({ 'left': this.position+'%' })
.bind(mousedown, $.proxy( this, "startMoving" ));
},
startMoving: function(event){
event.preventDefault();
this.select();
gradienteditor.gradientOffset = gradienteditor.$gradient.offset();
$(document).bind('mousemove.global', $.proxy(this, "move") );
// add event listener to listen to input field changes
// show percentage in the input field
},
move: function(event){
// stay in the range of the previous and following step +/- 5 (min 5, max 95)
// if position is 55-65 round to 50
// update input field value
},
show: function(){
this.$el.addClass('visible');
},
hide: function(){
this.$el.removeClass('visible');
},
select: function(){
this.$el.addClass('selected');
},
unselect: function(){
this.$el.removeClass('selected');
}
},
addPicker: function(position, rgb){
return $('<div class="picker bottom" />')
.css({ 'left': position+'%' })
.attr({
'data-color': JSON.stringify(rgb),
'data-percentage': position
})
.bind({
mousedown: $.proxy( this, "selectPicker" ),
dblclick: $.proxy( this, "startPicking" )
})
.append($('<div class="arrow" />'))
.append($('<div class="box" />')
.append($('<div class="color_field" />').css({ 'background': tools.toColor(rgb) }))
);
},
selectPicker: function(event){
event.preventDefault();
var obj = $(event.target).parents('.picker');
this.selectStop(obj);
this.showMiddlepoints(obj);
this.gradientOffset = this.$gradient.offset();
this.extract();
$(document).bind('mousemove.global', $.proxy(this, "movePicker") );
$(document).one('mouseup', $.proxy(this, "stopPicking") );
},
startPicking: function(event){
event.preventDefault();
colorpicker.pick(this.currentStopColor, this.updatePicker, this);
},
stopPicking: function(){
if(this.changed){
this.currentPick.attr('data-percentage', this.currentPercentage);
}
},
extract: function(){
this.tempStops = this.expand( $.extend(true, [], this.currentGradient.stops) );
this.tempStops.splice(this.currentPosition,1);
},
inject: function(percentage){
if(this._percentage === undefined || percentage !== this._percentage){
var injectedStops = $.extend(true, [], this.tempStops),
pos = injectedStops.length,
stop = [this.currentStopColor, percentage];
for(var i = 0, l = injectedStops.length; i<l; i++){
var tempStop = injectedStops[i];
if(typeof tempStop === 'object' && tempStop[1] > percentage){
pos = i;
break;
}
}
injectedStops.splice(pos, 0, stop);
this.updateGradient( this.shrink(injectedStops) );
this._percentage = percentage;
}
},
expand: function(stops){
var last = stops.length-1;
if(stops[0].length === 3) stops[0] = [stops[0], 0];
if(stops[last].length === 3) stops[last] = [stops[last], 100];
return stops;
},
shrink: function(stops){
var last = stops.length-1;
if(stops[0][1] === 0) stops[0] = stops[0][0];
if(stops[last][1] === 100) stops[last] = stops[last][0];
return stops;
},
getArrayPos: function(percentage, stops){
for(var i = 0, l = stops.length; i<l; i++){
var stop = stops[i];
if(typeof stop === 'object'){
if(percentage === 0 || percentage === 100){
return percentage === 0 ? 0 : l-1;
}
if(stop[1] === percentage){
return i;
}
}
}
},
movePicker: function(event){
event.preventDefault();
var x = Math.max(0, Math.min(this.gradientDimensions.width, event.pageX-this.gradientOffset.left)),
y = 33,
percentage = Math.round(x/this.gradientDimensions.width*100);
if( // out of range - remove gesture
event.pageX < (this.gradientOffset.left - 26) ||
event.pageX > (this.gradientOffset.left + this.gradientDimensions.width + 26) ||
event.pageY < (this.gradientOffset.top - 26) ||
event.pageY > (this.gradientOffset.top + this.gradientDimensions.height + 69) ){
// more than 2 color stops
if(!this._hasMinimumSize){
x = event.pageX - this.gradientOffset.left;
y = event.pageY - this.gradientOffset.top;
if (this.puff === null) {
this.puff = $('<div id="puff" />').appendTo($body);
$(document).bind('mouseup.puff', $.proxy( this, "removeCurrentPicker" ));
}
this.puff.css({ 'left': event.pageX+2, 'top': event.pageY+16 });
this.updateGradient( this.shrink(this.tempStops) );
}
}
else {
// move picker
this.currentPercentage = percentage;
this.$stopLocation.val(percentage);
this.inject(percentage);
if(!this.changed){
this.$gradientName.val(lang.Custom);
this.changed = true;
};
if(this.puff != null){
$(document).unbind('mouseup.puff');
$('#puff').remove();
this.puff = null;
}
}
$(this.currentPick).css({ 'left': x+'px', 'top': y+'px' });
},
removeCurrentPicker: function(event){
this.puff = null;
$('#puff').remove();
$(this).unbind(event);
},
updatePicker: function(newColor){
var colorString, stops;
// newColor RGB-{Array}
if(!this.changed){
this.$gradientName.val(lang.Custom);
this.changed = true;
};
colorString = tools.toColor(newColor);
$(this.currentPick).attr('data-color', JSON.stringify(newColor));
this.currentColorField.css("background", colorString);
this.$stopColor.css("background", colorString);
stops = gradienteditor.currentGradient.stops;
// search for the position and inject new color
if(this.currentPosition > 0 && this.currentPosition < stops.length-1){
stops[this.currentPosition][1] = newColor;
}
else {
stops[this.currentPosition] = newColor;
}
this.updateGradient(stops);
},
addMiddlepoint: function(position, realpos){
return $('<span class="middlepoint bottom"><span /></span>')
.attr({
'data-percentage': realpos,
})
.css({ 'left': position+'%' })
.bind({
mousedown: function(e){
gradienteditor.selectStop(this);
//gradienteditor.selectMiddlePoint(this);
}
});
},
updateGradient: function(stops){
gradienteditor.currentGradient.stops = stops;
this.$gradient.css('background', css.cssGradient( stops, 0, "linear" ));
if(gradienteditor.callback) gradienteditor.callback.call(gradienteditor.thisArg, stops);
},
setGradient: function(gradient){
this.hideStop();
this.currentGradient = $.extend(true, [], gradient);
this.$gradient.css('background', css.cssGradient( this.currentGradient.stops, 0, "linear" ));
this.$gradientName.val(this.currentGradient.name);
this.$gradient.children().remove();
var helpers = $('<div/>');
for(var i=0,length = this.currentGradient.stops.length; i<length; i++){
var stop = this.currentGradient.stops[i];
var pos, color;
switch(typeof stop){
case 'object': // => [255,255,255] or [[255,255,255], 33]
if(stop.length === 3){ // => [255,255,255]
color = stop;
pos = i === 0 ? 0 : 100;
}
else {
color = stop[0];
pos = stop[1];
}
helpers.append( this.addPicker(pos, color) );
if(typeof this.currentGradient.stops[i+1] !== 'number' && i != length-1){
var nextStop = this.currentGradient.stops[i+1];
var nextPos = nextStop.length !== 3 ? nextStop[1] : 100;
helpers.append( this.addMiddlepoint(tools.getCenter(pos, nextPos), 50) );
}
break;
case 'number':
var middlepoint = tools.getMiddlepoint(this.currentGradient.stops[i-1], stop, this.currentGradient.stops[i+1]);
helpers.append( this.addMiddlepoint(middlepoint[1], middlepoint[1]) );
break;
}
}
this.$gradient.append(helpers);
},
addGradientPreset: function(name, stops){
var preset = $('<div class="swatch" />')
.attr({'title': name})
.css({
'background': css.cssGradient( stops, 135, "linear" )
})
.bind('click', $.proxy( this, "handlePreset" ))
return preset.get(0);
},
handlePreset: function(e){
e.stopPropagation();
// find out the gradients position in the gradient array
var family = $(e.target).parent().children();
var pos = family.index(e.target);
// if alt is pressed while clicking: remove gradient
if(e.altKey){
// slice out the gradient from the gradient array (method by John Resig)
var rest = this.gradients.slice(pos + 1);
this.gradients.length = pos;
this.gradients.push.apply(this.gradients, rest);
localStorage["gradients"] = JSON.stringify(this.gradients);
$(e.target).remove();
}
else {
// else get the gradient
this.setGradient(this.gradients[pos]);
this.updateGradient(this.gradients[pos].stops);
}
},
showStop: function(pos, color){
this.$stopLocation.prop("disabled", false).val(pos).parent().removeClass("disabled");
if (color !== null) {
if(!this._hasMinimumSize) this.$removeStop.prop("disabled", false);
this.$stopColor.css({'background-color': color}).parent().removeClass("disabled");
this.$stopColor.bind('mousedown', $.proxy( this, "startPicking" ));
}
else {
this.$removeStop.prop("disabled", true);
this.$stopColor.css({'background-color': 'transparent'}).parent().addClass("disabled");
}
},
updateStopColor: function(color){
this.$stopColor.css({'background-color': color});
},
hideStop: function(){
this.$removeStop.prop("disabled", true);
this.$stopLocation.prop("disabled", true).val("").parent().addClass("disabled");
this.$stopColor.css({'background-color': 'transparent'}).parent().addClass("disabled");
},
selectStop: function(object){
var $o = $(object), color;
this.currentPick = $o;
this.currentPercentage = parseInt($o.attr('data-percentage'), 10);
this.currentPosition = this.getArrayPos(this.currentPercentage, this.currentGradient.stops);
this.currentColorField = $o.find('.color_field');
color = $o.attr('data-color');
this.currentStopColor = color ? JSON.parse(color) : null;
this._hasMinimumSize = this.currentGradient.stops.length == 2 ? true : false;
this.showStop(this.currentPercentage, this.currentStopColor);
$o.siblings().removeClass('selected');
$o.addClass('selected');
},
showMiddlepoints: function(object){
$(object).siblings('span').removeClass('visible');
$(object).next('span').add($(object).prev('span')).addClass('visible');
},
cancelAction: function(){
gradienteditor.updateGradient(gradienteditor.prevStops);
nav.goTo(1);
},
okAction: function(){
nav.goTo(1);
},
newAction: function(){
if(this.changed){
var newGradient = {
'name': this.$gradientName.val(),
'stops': this.currentGradient.stops
};
this.gradients.push(newGradient);
this.renderPresets([newGradient]);
localStorage["gradients"] = JSON.stringify(this.gradients);
this.changed = false;
};
},
renderPresets: function(gradients){
var presets = document.createDocumentFragment();
for(var i = 0, length = gradients.length; i<length; i++){
presets.appendChild( this.addGradientPreset(gradients[i].name, gradients[i].stops) );
}
this.$gradientPresets.append(presets);
},
init: function(){
this.$o = $('#gradient_editor');
this.$gradientPresets = $('#gradient_presets');
this.$gradientName = $('#gradient_name');
this.$gradientHolder = $('#gradient_holder');
this.$gradient = $('#gradient');
this.$stopColor = $('#stop_color');
this.$stopLocation = $('#stop_location');
this.$removeStop = $('#remove_stop');
this.$okButton = $('#gradient_ok');
this.$cancelButton = $('#gradient_cancel');
this.$newButton = $('#gradient_new');
if(localStorage["gradients"]) this.gradients = JSON.parse(localStorage["gradients"]);
this.currentGradient = this.gradients[0];
this.setGradient(this.currentGradient);
// draw gradient presets
this.renderPresets(this.gradients);
this.$removeStop.click( $.proxy( this, "removeCurrentPicker") );
this.$cancelButton.click( $.proxy( this, "cancelAction" ) );
this.$okButton.click( $.proxy( this, "okAction" ) );
this.$newButton.click( $.proxy( this, "newAction" ) );
this.$gradientName.mousedown( function(e){ e.stopPropagation(); });
this.$stopLocation.bind({
mousedown: function(e){ e.stopPropagation(); },
focus: function(e){ numbers.initNumberField(this, 'style'); },
keydown: numbers.restrictCharacters,
keyup: numbers.keyUp,
blur: numbers.validateInput
});
this.gradientDimensions = { 'width': this.$gradient.width(), 'height': this.$gradient.height() };
}
};
================================================
FILE: js/localization.js
================================================
var localization = {
en: {
"Color": "Color",
"Opacity": "Opacity",
"Angle": "Angle",
"Distance": "Distance",
"Spread": "Spread",
"Size": "Size",
"DropShadow": "Drop Shadow",
"InnerShadow": "Inner Shadow",
"Background": "Background",
"Border": "Border",
"new": "new",
"current": "current",
"PickAColor": "Pick a Color",
"GradientEditor": "Gradient Editor",
"Ok": "Ok",
"Cancel": "Cancel",
"NewStyle": "New Style",
"ColorSwatchName": "Color Swatch Name",
"ClosestValueInserted": "Closest value inserted",
"AnIntegerBetween": "An integer between",
"and": "and",
"isRequired": "is required",
"Custom": "Custom",
"DeleteStyle": "Delete Style"
},
de: {
"Color": "Farbe",
"Opacity": "Transparenz",
"Angle": "Winkel",
"Distance": "Abstand",
"Spread": "Umfang",
"Size": "Größe",
"DropShadow": "Schlagschatten",
"InnerShadow": "Innerer Schatten",
"Background": "Hintergrund",
"Border": "Rahmen",
"new": "neu",
"current": "momentan",
"PickAColor": "Wähl eine Farbe",
"GradientEditor": "Verlaufs Editor",
"Ok": "Ok",
"Cancel": "Abbrechen",
"NewStyle": "Neuer Style",
"ColorSwatchName": "Farbfeld Name",
"ClosestValueInserted": "Naheliegendste Zahl eingesetzt",
"AnIntegerBetween": "Eine Zahl zwischen",
"and": "und",
"isRequired": "wird benötigt",
"Custom": "Unbekannt",
"DeleteStyle": "Style löschen"
}
}
================================================
FILE: js/numbers.js
================================================
var numbers = {
regex: new RegExp(''),
min: 0,
max: 0,
temporaryMode: "",
match: false,
pressed: false,
speed: 0,
value: "",
type: "",
direction: 0,
DIGITS: /[-1234567890]/g,
HEXCODE: /[A-Fa-f0-9]/g,
// control Keys: 8 = backspace, 9 = tab, 13 = enter, 35 = home, 37 = left, 38 = top, 39 = right, 40 = down
controlKeys: [ 8, 9, 13, 35, 36, 37, 38, 39, 40 ],
// cut, copy & paste keys are 67 = c, 86 = v and 88 = x additional 65 = a ('select all')
cutCopyPasteKeys: [ 65, 67, 86, 88 ],
numpadKeys: { 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9" },
initNumberField: function(input, type) {
numbers.type = type;
numbers.$input = $(input);
numbers.max = numbers.$input.attr('data-max');
numbers.min = numbers.$input.attr('data-min');
numbers.restrict = numbers.DIGITS;
numbers.temporaryMode = numbers.$input.attr('id');
switch (numbers.max) {
case "10": // 0-10
numbers.regex.compile("^(0|([1-9]{1}|10))$");
break;
case "100": // 0-100
numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|100))$");
break;
case "200": // 0-200
numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|[1]{1}[0-9]{0,2}|200))$");
break;
case "255": // 0-255
numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|[1]{1}[0-9]{0,2}|[2]{1}([0-4]{1}[0-9]{1}|[5]{1}[0-5]{1})))$");
break;
case "360": // 0-360
numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|[1-2]{1}[0-9]{0,2}|[3]{1}([0-5]{1}[0-9]{1}|[6]{1}[0]{1})))$");
break;
}
},
initHexField: function(input, type) {
numbers.type = type;
numbers.$input = $(input);
numbers.temporaryMode = numbers.$input.attr('id');
numbers.regex.compile("^([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$");
numbers.restrict = numbers.HEXCODE;
},
keyUp: function(event) {
var keycode;
if (event.keyCode) {
keycode = event.keyCode;
}
else if (event.which) {
keycode = event.which;
}
clearTimeout(numbers.timeout);
numbers.value = numbers.$input.val();
if(numbers.regex.test(numbers.value)){
numbers.match = true;
if(!numbers.pressed){
numbers.updateField();
} else {
numbers.pressed = false;
}
}
if(keycode === 91){
numbers.commandKeyPressed = false;
}
},
updateField: function() {
switch(numbers.type){
case 'color':
if (numbers.match && numbers.value !== "") colorpicker.update(numbers.temporaryMode);
break;
case 'style':
if (numbers.value !== "") numbers.$input.change();
break;
}
},
restrictCharacters: function(event) {
var keycode, character, isControlKey, isCopyCutPasteKey;
// future:
// - allow copy & paste shortcuts ('windows/apple': 91, 'v': 86, 'c': 67, 'x': 88)
// set boolean for 91 - next click: check for boolean and set false
// oh - on windows it's strg+c and strg+v (check ctrlKey)
//
// - allowe to paste hexcodes including a '#' at the beginning: slice it out
numbers.value = numbers.$input.val();
if (event.keyCode) {
keycode = event.keyCode;
}
else if (event.which) {
keycode = event.which;
}
// if pressed key is a numeric pad key use the numpad map object to detect its number
if(keycode >= 96 && keycode <= 105){
character = numbers.numpadKeys[keycode];
} else {
character = String.fromCharCode(keycode);
}
if(numbers.commandKeyPressed){
isCopyCutPasteKey = numbers.copyCutPasteKeys.join(",").match(new RegExp(keycode));
if(isCopyCutPasteKey){
return true;
}
}
if(keycode === 91) {
numbers.commandKeyPressed = true;
return false;
}
// 1 for key up (keycode 38), -1 for key down (keycode 40), 0 for other keys
numbers.direction = 0;
switch(keycode){
case 38: numbers.direction = 1; break;
case 40: numbers.direction = -1; break;
}
if (numbers.direction !== 0 && numbers.restrict === numbers.DIGITS) {
numbers.accelerate();
return false;
}
else {
isControlKey = numbers.controlKeys.join(",").match(new RegExp(keycode));
if (isControlKey) {
return true;
}
else if (character.match(numbers.restrict)) {
numbers.value += character;
return true;
}
event.preventDefault();
return false;
}
},
accelerate: function() {
if(numbers.timeout) clearTimeout(numbers.timeout);
if(numbers.value === '') {
numbers.value = 0;
}
var number = parseInt(numbers.value, 10);
number += numbers.direction;
number = Math.max(numbers.min, Math.min(numbers.max, number));
if('-'+numbers.max === numbers.min) { // as in angle from -180 to 180
if(number === numbers.min) number = numbers.max;
else if(number === numbers.max) number = numbers.min;
}
numbers.$input.val(number);
numbers.value = number;
numbers.updateField();
if(!numbers.pressed){
numbers.speed = 500;
numbers.pressed = true;
}
else {
numbers.speed = 150;
}
numbers.timeout = setTimeout(function(){ jQuery.proxy(numbers, "accelerate") }, numbers.speed);
},
validateInput: function(event) {
var integer, errorString, nearestInt;
numbers.value = numbers.$input.val();
integer = parseInt(numbers.value, 10);
if(numbers.regex.test(integer)){
console.log(integer);
numbers.$input.val(integer ? integer : "");
return true;
}
event.preventDefault();
errorString = lang.AnIntegerBetween+" "+ numbers.min +" "+lang.and+" "+ numbers.max +" "+lang.isRequired+". "+lang.ClosestValueInserted+".";
alert(errorString);
nearestInt = Math.abs(numbers.max - integer) < Math.abs(numbers.min - integer) ? numbers.max : numbers.min;
numbers.$input.val(nearestInt).focus().change();
}
};
================================================
FILE: js/style.js
================================================
var style = {
background: {
elements: {
".opacity": { name: "opacity", handle: "slider" },
".gradientField": "gradientField",
".reverse": "reverse",
".angle": { name: "angle", handle: "pot" },
".globalLight": "globalLight"
},
$styles: $('#background_style'),
init: function(el){
this.$el = $("#"+el);
this.selector = el;
this.$menuItem = $('.nav-'+el);
this.$checkbox = this.$menuItem.find('input[type=checkbox]');
this.$inputs = this.$el.find('input[type=text]');
this.initElements();
this.updateStops();
this.$gradientField.click( $.proxy( this, "edit" ) );
this.$reverse.change( $.proxy( this, "switchReverse" ) );
this.$globalLight.click( $.proxy( this, "switchLight" ) );
this.$checkbox.click( $.proxy( this, "check" ) );
this.$menuItem.click( $.proxy( this, "select" ) );
this.$styles.change( $.proxy( this, "updateStyle" ) );
$(document).bind('styleChange', $.proxy( this, "populateInputs" ));
},
initElements: function(){
for (var key in this.elements) {
var el = this.elements[key];
if(typeof el === 'object'){
this["$"+el.name] = $(key, this.$el);
switch(el.handle){
case "slider":
this[el.name+"Slider"] = Object.create(slider);
this[el.name+"Slider"].init(this.selector, el.name);
break;
case "pot":
this[el.name+"Pot"] = Object.create(pot);
this[el.name+"Pot"].init(this.selector);
break;
}
} else {
this["$"+el] = $(key, this.$el);
}
}
},
populateInputs: function(){
this.setActive();
this.opacitySlider.update(currentStyle[this.selector].opacity);
this.updateStops();
this.setReverse();
this.displayStyle();
this.setLight();
},
select: function(){
if(!currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = true;
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
this.paint();
}
},
check: function(e){
e.stopPropagation();
if(currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = false;
} else {
currentStyle[this.selector].isActive = true;
}
this.setActive();
this.paint();
},
setActive: function(){
if(currentStyle[this.selector].isActive){
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
} else {
this.$checkbox.prop('checked', false);
this.$el.addClass('inactive');
this.$inputs.prop('disabled', true);
}
},
edit: function(){
gradienteditor.edit(currentStyle[this.selector].stops, this.updateStops, this);
},
setReverse: function(){
if(currentStyle[this.selector].isReverse){
this.$reverse.prop('checked', true);
} else {
this.$reverse.prop('checked', false);
}
this.updateStops();
this.paint();
},
switchReverse: function(){
if(currentStyle[this.selector].isReverse){
currentStyle[this.selector].isReverse = false;
} else {
currentStyle[this.selector].isReverse = true;
}
this.setReverse();
},
setLight: function(){
if(currentStyle[this.selector].hasGlobalLight){
this.$globalLight.prop('checked', true);
this.anglePot.update(currentStyle.globalAngle);
} else {
this.$globalLight.prop('checked', false);
this.anglePot.update(currentStyle[this.selector].angle);
}
},
switchLight: function(){
if(currentStyle[this.selector].hasGlobalLight){
currentStyle[this.selector].hasGlobalLight = false;
} else {
currentStyle[this.selector].hasGlobalLight = true;
}
this.setLight();
this.paint();
},
updateStyle: function(){
currentStyle[this.selector].style = this.$styles.val();
this.paint();
},
displayStyle: function(){
this.$styles.val(currentStyle[this.selector].style);
},
updateStops: function(stops){
if(stops){
currentStyle[this.selector].stops = stops;
currentStyle[this.selector].translucidStops = $.extend(true, [], stops);
this.paint();
}
this.$gradientField.css('background', css.cssGradient( currentStyle[this.selector].stops, currentStyle[this.selector].isReverse ? 180 : 0, "linear" ));
},
paint: function(){
$(document).trigger('paint');
}
},
shadow: {
elements: {
".opacity": { name: "opacity", handle: "slider" },
".color_field": "color",
".angle": { name: "angle", handle: "pot" },
".globalLight": "globalLight",
".distance": { name: "distance", handle: "slider" },
".blur": { name: "blur", handle: "slider" },
".size": { name: "size", handle: "slider" }
},
init: function(el){
this.$el = $("#"+el);
this.selector = el;
this.$menuItem = $('.nav-'+el);
this.$checkbox = this.$menuItem.find('input[type=checkbox]');
this.$inputs = this.$el.find('input[type=text]');
this.initElements();
this.updateColor();
this.$color.click( $.proxy( this, "pick" ) );
this.$checkbox.click( $.proxy( this, "check" ) );
this.$menuItem.click( $.proxy( this, "select" ) );
this.$globalLight.click( $.proxy( this, "switchLight" ) );
$(document).bind('styleChange', $.proxy( this, "populateInputs" ));
},
initElements: function(){
for (var key in this.elements) {
var el = this.elements[key];
if(typeof el === 'object'){
this["$"+el.name] = $(key, this.$el);
switch(el.handle){
case "slider":
this[el.name+"Slider"] = Object.create(slider);
this[el.name+"Slider"].init(this.selector, el.name);
//if(el.autoUpdate) currentStyle[this.selector].__defineSetter__( el.name , $.proxy( this[el.name+"Slider"], "set" ) );
break;
case "pot":
this[el.name+"Pot"] = Object.create(pot);
this[el.name+"Pot"].init(this.selector);
break;
}
} else {
this["$"+el] = $(key, this.$el);
}
}
},
populateInputs: function(){
this.setActive();
this.updateColor();
this.opacitySlider.update(currentStyle[this.selector].opacity);
this.distanceSlider.update(currentStyle[this.selector].distance);
this.blurSlider.update(currentStyle[this.selector].blur);
this.sizeSlider.update(currentStyle[this.selector].size);
this.setLight();
},
select: function(){
if(!currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = true;
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
this.paint();
}
},
check: function(e){
e.stopPropagation();
if(currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = false;
} else {
currentStyle[this.selector].isActive = true;
}
this.setActive();
this.paint();
},
setActive: function(){
if(currentStyle[this.selector].isActive){
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
} else {
this.$checkbox.prop('checked', false);
this.$el.addClass('inactive');
this.$inputs.prop('disabled', true);
}
},
pick: function(){
colorpicker.pick(currentStyle[this.selector].color, this.updateColor, this);
},
setLight: function(){
if(currentStyle[this.selector].hasGlobalLight){
this.$globalLight.prop('checked', true);
this.anglePot.update(currentStyle.globalAngle);
} else {
this.$globalLight.prop('checked', false);
this.anglePot.update(currentStyle[this.selector].angle);
}
},
switchLight: function(){
if(currentStyle[this.selector].hasGlobalLight){
currentStyle[this.selector].hasGlobalLight = false;
} else {
currentStyle[this.selector].hasGlobalLight = true;
}
this.setLight();
this.paint();
},
updateColor: function(currentColor){
if(currentColor){
currentStyle[this.selector].color = currentColor;
this.paint();
}
this.$color.css('background', '#'+color.hexFromRgb(currentStyle[this.selector].color));
},
paint: function(){
$(document).trigger('paint');
}
},
border: {
elements: {
".color_field": "color",
".opacity": { name: "opacity", handle: "slider" },
".size": { name: "size", handle: "slider" }
},
$styles: $('#border_styles').find('> div'),
init: function(el){
this.$el = $("#"+el);
this.selector = el;
this.$menuItem = $('.nav-'+el);
this.$checkbox = this.$menuItem.find('input[type=checkbox]');
this.$inputs = this.$el.find('input[type=text]');
this.initElements();
this.updateColor();
this.$color.click( $.proxy( this, "pick" ) );
this.$checkbox.click( $.proxy( this, "check" ) );
this.$menuItem.click( $.proxy( this, "select" ) );
this.$styles.click( $.proxy( this, "updateStyle" ) );
$(document).bind('styleChange', $.proxy( this, "populateInputs" ));
},
initElements: function(){
for (var key in this.elements) {
var el = this.elements[key];
if(typeof el === 'object'){
this["$"+el.name] = $(key, this.$el);
switch(el.handle){
case "slider":
this[el.name+"Slider"] = Object.create(slider);
this[el.name+"Slider"].init(this.selector, el.name);
break;
case "pot":
this[el.name+"Pot"] = Object.create(pot);
this[el.name+"Pot"].init(this.selector);
break;
}
} else {
this["$"+el] = $(key, this.$el);
}
}
},
populateInputs: function(){
this.setActive();
this.updateColor();
this.opacitySlider.update(currentStyle[this.selector].opacity);
this.sizeSlider.update(currentStyle[this.selector].size);
this.setStyle();
},
select: function(){
if(!currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = true;
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
this.paint();
}
},
check: function(e){
e.stopPropagation();
if(currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = false;
} else {
currentStyle[this.selector].isActive = true;
}
this.setActive();
this.paint();
},
setActive: function(){
if(currentStyle[this.selector].isActive){
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
} else {
this.$checkbox.prop('checked', false);
this.$el.addClass('inactive');
this.$inputs.prop('disabled', true);
}
},
pick: function(){
colorpicker.pick(currentStyle[this.selector].color, this.updateColor, this);
},
setStyle: function(){
for(var i=0, l=this.$styles.length; i<l; i++){
if(this.$styles.eq(i).data('style') === currentStyle[this.selector].style){
this.updateStyle(null, this.$styles.eq(i));
return false;
}
}
},
updateStyle: function(event, setStyle){
var obj = $(setStyle || event.target);
this.$styles.removeClass('active');
obj.addClass('active');
currentStyle[this.selector].style = obj.data('style');
this.paint();
},
updateColor: function(currentColor){
if(currentColor){
currentStyle[this.selector].color = currentColor;
this.paint();
}
this.$color.css('background', '#'+color.hexFromRgb(currentStyle[this.selector].color));
},
paint: function(){
$(document).trigger('paint');
}
},
borderRadius: {
$pixel: $('#border_radius_pixel'),
$percent: $('#border_radius_percent'),
$preview: $('#border_radius_preview'),
$topLeft: $('#topLeft'),
$topRight: $('#topRight'),
$bottomLeft: $('#bottomLeft'),
$bottomRight: $('#bottomRight'),
maxRadius: 200,
init: function(el){
this.$el = $("#"+el);
this.selector = el;
this.$menuItem = $('.nav-'+el);
this.$checkbox = this.$menuItem.find('input[type=checkbox]');
this.$inputs = this.$el.find('input[type=text]');
this.$radius = $('.radius', this.$el);
this.radiusSlider = Object.create(slider);
this.radiusSlider.init(this.selector, "radius");
this.$checkbox.click( $.proxy( this, "check" ) );
this.$menuItem.click( $.proxy( this, "select" ) );
this.$pixel.add(this.$percent).click( $.proxy( this, "updateUnit" ) );
this.$preview.mousedown( $.proxy( this, "startSelection" ) );
this.$fields = this.$preview.children();
$(document).bind('styleChange', $.proxy( this, "populateInputs" ));
},
populateInputs: function(){
this.setActive();
currentStyle[this.selector].radius = 0;
currentStyle[this.selector].__defineSetter__( "radius", $.proxy( this, "updateRadius" ) );
},
select: function(){
if(!currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = true;
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
this.paint();
}
},
check: function(e){
e.stopPropagation();
if(currentStyle[this.selector].isActive){
currentStyle[this.selector].isActive = false;
} else {
currentStyle[this.selector].isActive = true;
}
this.setActive();
this.paint();
},
setActive: function(){
if(currentStyle[this.selector].isActive){
this.$checkbox.prop('checked', true);
this.$el.removeClass('inactive');
this.$inputs.prop('disabled', false);
} else {
this.$checkbox.prop('checked', false);
this.$el.addClass('inactive');
this.$inputs.prop('disabled', true);
}
},
startSelection: function(event){
$(document).bind('mousemove.global', $.proxy( this, "updateSelection" ) );
this.currentTarget = event.target;
$(event.target).toggleClass("active");
$(document).one('mouseup', $.proxy( this, "setSelection" ) );
},
updateSelection: function(event){
if(event.target != this.currentTarget){
$(event.target).toggleClass("active");
this.currentTarget = event.target;
}
},
updateRadius: function(value){
for(var i=0; i<4; i++){
if(currentStyle[this.selector].isSelected[i]){
currentStyle[this.selector].radii[i] = currentStyle[this.selector].hasPercentage[i] ? [value, "%"] : [value, "px"];
}
}
this.paint();
},
setSelection: function(e){
var value, sum = 0, amount = 0, average = 0, equal = false;
for(var i=0; i<4; i++){
if(this.$fields.eq(i).hasClass("active")){
currentStyle[this.selector].isSelected[i] = true;
// count the sum of all radii
value = parseInt(currentStyle[this.selector].radii[i][0], 10);
sum+=value;
amount++;
if(sum/amount === value){
equal = true;
} else {
equal = false;
}
} else {
currentStyle[this.selector].isSelected[i] = false;
}
}
// set radius value (average) but don't set css
average = amount === 0 ? 0 : Math.floor(sum/amount);
value = equal ? average : 0;
this.radiusSlider.set(value);
this.radiusSlider.move(this.radiusSlider.toPos(value));
},
updateUnit: function(event){
var $el = $(event.target), average, sum = 0, amount = 0;
switch($el.attr('data-unit')){
case "%":
for(var i=0; i<4; i++){
if(currentStyle[this.selector].isSelected[i]){
var radius = currentStyle[this.selector].radii[i][0];
// recalculate value from pixel to percent and limit to 50
var value = Math.floor(Math.min(50, radius*100/currentStyle.height)); // height or width?
currentStyle[this.selector].radii[i] = [value, "%"];
currentStyle[this.selector].hasPercentage[i] = true;
sum += value;
amount++;
}
}
// limit slider to 50
this.radiusSlider.max = 50;
// uncheck pixel button
this.$pixel.removeClass("active");
break;
case "px":
for(var i=0; i<4; i++){
if(currentStyle[this.selector].isSelected[i]){
var radius = currentStyle[this.selector].radii[i][0];
// recalculate value from percent to pixel and limit to maxRadius
var value = Math.floor(Math.min(currentStyle[this.selector].maxRadius, radius*currentStyle.height/100)); // height or width?
currentStyle[this.selector].radii[i] = [value, "px"];
currentStyle[this.selector].hasPercentage[i] = false;
sum += value;
amount++;
}
}
// reset limit
this.radiusSlider.max = this.maxRadius;
// uncheck percent button
this.$percent.removeClass("active");
break;
}
average = Math.floor(sum/amount);
// update input value to the average value and trigger change() to adjust the slider
this.radiusSlider.set(average);
this.radiusSlider.move(this.radiusSlider.toPos(average));
$el.addClass("active");
this.paint();
},
paint: function(){
$(document).trigger('paint');
}
},
init: function(){
this.background.init("background");
this.dropShadow = Object.create(style.shadow);
this.dropShadow.init("dropShadow");
this.innerShadow = Object.create(style.shadow);
this.innerShadow.init("innerShadow");
this.border.init("border");
this.borderRadius.init("borderRadius");
}
};
================================================
FILE: js/styleStore.js
================================================
var styleStore = {
styles: [
{
name: "Default Style",
style: { }
},
{
name: "Inset Box",
style: {
dropShadow: { color: [255,255,255], opacity: 100, blur: 0 },
innerShadow: { color: [0,0,0], opacity: 40, blur: 7 },
background: { stops: [[191, 191, 191], 11, [[242, 242, 242], 88], 77, [252, 252, 252]], reverse: true }
}
},
{
name: "Vista Inset Box",
style: {
dropShadow: { color: [255,255,255], opacity: 50, blur: 0 },
innerShadow: { color: [0,0,0], opacity: 40, blur: 7 },
background: { stops: [[116,116,116], [[109,109,109], 50], [[126,126,126], 50], [133,133,133]] },
border: { isActive: false },
borderRadius: { radii: [[10, "px"],[10, "px"],[10, "px"],[10, "px"]] }
}
},
{
name: "Hello Red",
style: {
dropShadow: { color: [255,255,255], opacity: 14, blur: 0 },
innerShadow: { color: [255,255,255], opacity: 21 },
background: { stops: [[213,87,91], [196,48,51]] },
border: { color: [168,0,2] },
borderRadius: { radii: [[5, "px"],[5, "px"],[5, "px"],[5, "px"]] }
}
},
{
name: "Orange Box",
style: {
dropShadow: { isActive: false },
innerShadow: { color: [249,169,88], distance: 0, size: 1 },
background: { stops: [[255, 225, 173], 42, [[250, 169, 28], 12], 91, [217, 97, 4]] },
border: { color: [153,102,52] },
borderRadius: { radii: [[2, "px"],[2, "px"],[2, "px"],[2, "px"]] }
}
},
{
name: "Apple Promo Box",
style: {
dropShadow: { color: [0,0,0], opacity: 40, blur: 3 },
innerShadow: { color: [255,255,255], opacity: 100, distance: 0, size: 3 },
background: { stops: [[250,250,250], [238,238,238]] },
border: { isActive: false },
borderRadius: { radii: [[5, "px"],[5, "px"],[5, "px"],[5, "px"]] }
}
},
{
name: "iPhone Copy Button",
style: {
dropShadow: { color: [0,0,0], opacity: 55, distance: 3, blur: 4 },
innerShadow: { color: [255,255,255], opacity: 50 },
background: { stops: [[112, 134, 255], [[79, 105, 255], 37], [[53, 83, 255], 41], [49, 79, 254]] },
border: { color: [50,50,50] },
borderRadius: { radii: [[5, "px"],[5, "px"],[5, "px"],[5, "px"]] }
}
},
{
name: "Please don't sue me",
style: {
dropShadow: { distance: 0 },
innerShadow: { opacity: 55 },
background: { stops: [[22, 127, 232], [0, 60, 123]] }
}
}
],
init: function(){
this.$el = $('#stylePresets');
if(localStorage["styles"]) this.styles = JSON.parse(localStorage["styles"]);
this.renderStyles(this.styles);
this.loadStyle(0);
},
renderStyles: function(styleObjects){
var styleFragment = document.createDocumentFragment();
for(var i = 0, length = styleObjects.length; i<length; i++){
styleFragment.appendChild( this.addStyle(styleObjects[i].name, styleObjects[i].style, i) );
}
this.$el.append(styleFragment);
},
addStyle: function(name, packedStyle, pos){
var expandedStyle = this.decompress(packedStyle);
var cssObj = css.displayCss(expandedStyle);
var swatch = $('<div class="swatch" />')
.attr({ 'title': name, 'data-pos': pos })
.bind('mousedown', { self : this }, styleStore.select )
.append( $('<div />').css(cssObj) );
return swatch.get(0);
},
select: function(e){
e.stopPropagation();
var self = e.data.self;
var $obj = $(this);
var family = $obj.parent().children();
var pos = family.index(this);
// if alt is pressed while clicking: remove style
if(e.altKey){
// double check - styles are precious
if(pos !== 0 && window.confirm( lang.DeleteStyle + ' "'+ self.styles[pos].name +'"?' )){
// slice out the gradient from the gradient array (method by John Resig)
var rest = self.styles.slice(pos + 1);
self.styles.length = pos;
self.styles.push.apply(self.styles, rest);
localStorage["styles"] = JSON.stringify(self.styles);
$obj.remove();
}
}
else {
// else set the style
family.removeClass('active');
self.loadStyle(pos);
}
},
compress: function(style){
var slimStyle = {};
var fatStyle = $.extend(true, {}, style);
for( key in fatStyle ){
var value = fatStyle[key];
if(typeof style === "object"){
if(value.isActive){
slimStyle[key] = {};
for( prop in value ){
var propVal = value[prop];
if( defaults[key][prop] === undefined ) continue;
if( typeof propVal === "object" ){
if( !jQuery.compare(propVal, defaults[key][prop]) ){
slimStyle[key][prop] = propVal;
}
}
else if( propVal != defaults[key][prop] && prop !== "isActive" ){
slimStyle[key][prop] = propVal;
}
}
if( jQuery.isEmptyObject(slimStyle[key]) ) delete slimStyle[key];
} else {
if(defaults[key].isActive){
slimStyle[key] = { isActive: false };
}
}
}
else if(key === "globalAngle" && value !== defaults.globalAngle){
slimStyle["globalAngle"] = value;
}
}
return slimStyle;
},
decompress: function(packedStyle){
var expandedStyle = $.extend(true, {}, defaults);
for(key in packedStyle){
expandedStyle[key] = $.extend({}, defaults[key], packedStyle[key]);
if(packedStyle[key].isActive !== undefined){
expandedStyle[key].isActive = packedStyle[key].isActive;
} else {
expandedStyle[key].isActive = true;
}
}
return expandedStyle;
},
loadStyle: function(pos){
this.$el.children().eq(pos).addClass('active');
currentStyle = this.decompress(this.styles[pos].style);
$(document).trigger('styleChange').trigger('paint');
},
create: function(){
var newStyle, name = prompt(lang.NewStyle,"Style "+this.styles.length);
if(name){
newStyle = {'name': name, 'style': this.compress(currentStyle)};
this.styles.push(newStyle);
this.renderStyles([newStyle]);
localStorage["styles"] = JSON.stringify(this.styles);
}
}
}
================================================
FILE: js/tools.js
================================================
var tools = {
options: {
hex: true
},
/**
* @method averageGradientColor
* @param fullStops {stops-array}
* @return color {string}
* @example averageGradientColor([[255,255,255], [0,0,0]]) returns gray
*/
averageGradientColor: function(fullStops){
var stops = gradienteditor.expand( $.extend(true, [], fullStops) ),
reducedArray = [],
l = stops.length;
for(var i = 0; i < l; i++){
var stop = stops[i];
if(typeof stop === 'number'){
stops[i] = this.getMiddlepoint(stops[i-1], stop, stops[i+1]);
}
}
for(var i = 0; i < l-1; i++){
var stopA = stops[i],
stopB = stops[i+1];
reducedArray.push(this.averageStop(stopA, stopB));
}
// reduce array to one rgb array
reducedArray = reducedArray.reduce(this.averageColor, [0,0,0]);
// round its values
for(var i=0; i<3; i++){
reducedArray[i] = Math.round(reducedArray[i]);
}
// return said array as color string
return this.toColor(reducedArray);
},
/**
* @method averageStop
* @param stopA {stop-array}
* @param stopB {stop-array}
* @return color-stop {stop-array}
* @example averageStop([[255,255,255], 0], [[0,0,0], 100]) returns [[128,128,128], 50]
*/
averageStop: function(stopA, stopB){
var colorA = stopA[0],
posA = stopA[1],
colorB = stopB[0],
posB = stopB[1];
return [
[
this.getCenter(colorA[0],colorB[0]),
this.getCenter(colorA[1],colorB[1]),
this.getCenter(colorA[2],colorB[2])
],
posB - posA
];
},
/**
* @method averageColor
* @param previousValue {color-array}
* @param currentValue {stop-array}
* @return color {color-array}
*/
averageColor: function(previousValue, currentValue, index, array){
var color = currentValue[0],
weight = currentValue[1]/100;
return [
previousValue[0] + color[0] * weight, // r
previousValue[1] + color[1] * weight, // g
previousValue[2] + color[2] * weight // b
];
},
/**
* @method roundToMultiple
* @param number {integer}
* @param multiple {integer} multiple to round to
* @return rounded number {integer}
* @example roundToMultiple(35, 15) returns 30
* @usage in ui.js -> pot; to round to 15° steps
*/
roundToMultiple: function(number, multiple){
var value = number/multiple,
integer = Math.floor(value),
rest = value - integer;
return rest > 0.5 ? (integer+1)*multiple : integer*multiple;
},
/**
* @method toColor
* @param rgb {array} RGB or RGBA Color Array
* @return CSS Color {string}
* @example toColor([255,255,255]) returns 'rgb(255,255,255)'
* toColor([255,255,255,0.5]) returns 'rgba(255,255,255,0.5)'
*/
toColor: function(rgb){
var mode = rgb.length === 3 ? 'rgb' : 'rgba',
string = mode+'('+rgb.join(',')+')';
if (css.colors[string]) {
return css.colors[string];
}
else if(this.options.hex && mode === 'rgb'){
return "#"+color.hexFromRgb(rgb);
}
return string;
},
/**
* @method getCenter returns the center between a starting and an ending point
* @param start {integer}
* end {integer}
* offset {integer} [optional] if the center has an offset
* @return center {integer}
* @example getCenter(0, 60) returns 30
* getCenter(0, 60, 75) returns 45
*/
getCenter: function(start, end, offset){
var o = offset || 50;
return start + Math.round(o/100*(end-start));
},
/**
* @method getMiddlepoint returns the color at a specific position on a color gradient defined through a start and end color
* @param start {array} eiter a rgb color (like [255,255,255])or a rgb color and a positon (e.g. [[255,255,255], 10])
* pos {integer} position
* end {array} rgb color [r, g, b]
* @return {array} of the rgb color {array} and relative index {integer}
* @example getCenter(0, 60) returns 30
* getCenter(0, 60, 75) returns 45
*/
getMiddlepoint: function(start, pos, end){
var startColor = start,
endColor = end,
startIndex = 0,
endIndex = 100,
index = 0,
color = [];
if(start.length === 2){ startIndex = start[1]; startColor = start[0]; }
if(end.length === 2){ endIndex = end[1]; endColor = end[0]; }
index = this.getCenter(startIndex, endIndex, pos);
for (var i=0, l = startColor.length; i<l; i++) {
color[i] = startColor[i] + Math.round((endColor[i] - startColor[i])/2);
}
return [color, index];
},
/**
* @method decodeStops
* @param stops {array} encoded color stops
* @param alpha {float} [optional] opacity value between 0-1
* @return {array} decoded color stops: rgb strings
* @example decodeStops([0,0,0], 10, [255,255,255]) returns ['rgb(0,0,0)', 'rgb(25,25,25) 10%', 'rgb(255,255,255)']
*/
decodeStops: function(stops){
var steps = [];
for(var i=0, length=stops.length; i<length; i++){
var stop = stops[i];
switch(typeof stop){
case 'object': // => [255,255,255] or [[255,255,255], 33]
if(stop.length > 2){ // => [255,255,255]
steps[i] = this.toColor(stop);
}
else { // => [[255,255,255], 33]
steps[i] = this.toColor(stop[0])+" "+stop[1]+"%";
}
break;
case 'number': // => 11
var middlepoint = this.getMiddlepoint(stops[i-1], stop, stops[i+1]);
steps[i] = this.toColor(middlepoint[0])+" "+middlepoint[1]+"%";
break;
}
}
return steps;
},
/**
* @method decodeCanvasGradient
* @param stops {array} the color stops
* @param angle {integer} the gradients angle
* @param ctx {canvas 2d context} the context the gradient is for
* @param x {integer} the x coordinate where the gradient should start
* @param y {integer} the y coordinate where the gradient should start
* @param width {integer} the width of the gradients box
* @param height {integer} the height of the gradients box
* @return {canvas-gradient}
*/
decodeCanvasGradient: function(stops, angle, style, ctx, x, y, width, height){
var gradient,
// looks like stops is still referenced to currentStyle.background.translucentStops at this point
tempStops = $.extend(true, [], stops);
switch(style){
case "linear":
/* missing: angle support
0° -> x+width, y, x, y
45° -> x+width, y, x, y+height
90° -> x, y, x, y+height
135°-> x, y, x+width, y+height
180°-> x, y, x+width, y
225°-> x, y+height, x+width, y
270°-> x, y+height, x, y
315°-> x+width, y+height, x, y
there is a pattern :) something with sin & cos
for now now default to 90
*/
gradient = ctx.createLinearGradient(x, y, x, y+height);
break;
case "reflected":
tempStops = this.reflectStops(tempStops);
gradient = ctx.createLinearGradient(x, y, x, y+height);
break;
case "contain":
var closestSide = width < height ? width/2 : height/2;
gradient = ctx.createRadialGradient(x+width/2, y+height/2, 0, x+width/2, y+height/2, closestSide); // centered
break;
case "cover":
// farest corner = half diagonal side >> pitagoras
var farestCorner = Math.sqrt( width * width + height * height )/2;
gradient = ctx.createRadialGradient(x+width/2, y+height/2, 0, x+width/2, y+height/2, farestCorner); // centered
break;
}
// bring the stops in the right order for canvas gradient:
for(var i=0, length=tempStops.length; i<length; i++){
var stop = tempStops[i], color, pos;
// if the first stop has an offset add a color stop to 0
if(i === 0 && stop.length === 2){
gradient.addColorStop(0, this.toColor(stop[0]));
}
switch(typeof stop){
case 'object': // => [255,255,255] or [[255,255,255], 33]
if(stop.length === 3){ // => [255,255,255]
pos = i === 0 ? 0 : 100; // can either be the start or the end
color = this.toColor(stop);
}
else { // => [[255,255,255], 33]
color = this.toColor(stop[0]);
pos = stop[1];
}
break;
case 'number': // => 11
var middlepoint = this.getMiddlepoint(tempStops[i-1], stop, tempStops[i+1]);
color = this.toColor(middlepoint[0]);
pos = middlepoint[1];
break;
}
// pos is now between 0-100 - for canvas we need it between 0-1
pos = pos/100;
pos = pos+''; // <-- to change from number to string seems to fix a bug in firefox on ubuntu
gradient.addColorStop(pos, color);
}
return gradient;
},
/**
* @method opposite
* @param direction {String}
* @return {String} opposite direction
* @example opposite('top') returns 'bottom'
*/
opposite: function(direction) {
switch(direction){
case 'top':
return 'bottom';
case 'right':
return 'left';
case 'bottom':
return 'top';
case 'left':
return 'right';
}
},
reflectStops: function(stops){
var first = [],
second = [];
// bug: turns everything around
for(var i=0, l=stops.length; i<l; i++){
var stop = stops.shift(),
start, end;
switch(typeof stop){
case "number":
start = Math.round(stop/2);
end = 100-start;
break;
case "object":
start = stop.slice(0);
end = stop.slice(0);
if(stop.length === 2){
start[1] = Math.round(stop[1]/2);
end[1] = 100-start[1];
}
break;
}
// add 50% to the last element
if(i === l-1) start = [start, 50];
first.push(start);
// don't add the last stop cause we only need one center
if(i != l-1) second.unshift(end);
}
return first.concat(second);
},
reverseStops: function(stops){
var reversed = [],
stops = stops.slice(0);
while(stops.length){
var stop = stops.pop(), rev;
switch(typeof stop){
case "number":
rev = 100-stop;
break;
case "object":
rev = stop.slice(0);
if(stop.length === 2){
rev[1] = 100-stop[1];
}
break;
}
reversed.push(rev);
}
return reversed;
},
}
================================================
FILE: js/ui.js
================================================
var pot = {
init: function(el){
// el = background, dropShadow, innerShadow
this.$el = $("#"+el+" .pot");
this.height = this.$el.height();
this.width = this.$el.width();
this.$pointer = this.$el.find('> div');
this.model = el;
this.$el.bind("mousedown", $.proxy( this, "start" ) );
this.$input = this.$el.next('div').children('input:first-child');
this.$input.change( $.proxy( this, "get" ) );
},
start: function(event){
var myOffset = this.$el.offset();
this.offset = { x: myOffset.left+(this.width/2), y: myOffset.top+(this.height/2) };
this.turn(event);
$(document).bind('mousemove.global', $.proxy( this, "turn") );
},
get: function(){
var value = parseInt(this.$input.val());
this.update(value);
},
set: function(value){
this.$input.val(value);
},
update: function(value){
this.move(value);
if(currentStyle[this.model].hasGlobalLight) currentStyle.globalAngle = value;
currentStyle[this.model].angle = value;
this.set(value);
style[this.model].paint();
},
move: function(degrees){
this.$pointer.css('transform', 'rotate('+-degrees+'deg)');
},
turn: function(event){
event.preventDefault();
var opposite = this.offset.y - event.pageY,
adjacent = event.pageX - this.offset.x,
radiants = Math.atan(opposite/adjacent),
degrees = Math.round(radiants*(180/Math.PI), 10);
if(event.shiftKey) degrees = tools.roundToMultiple(degrees, 15);
if(adjacent < 0 && opposite >= 0){ degrees+= 180; }
else if(opposite < 0 && adjacent < 0){ degrees-= 180; }
if(degrees === -180) degrees = 180;
this.update(degrees);
}
};
var toggle = {
_treshhold: 2,
_moving: false,
init: function(el, toggle, thisArg, callback){
this.$el = $("#"+el);
this.$slider = this.$el.find('.slidePanel');
this.width = this.$el.width();
this.toggle = toggle;
this.model = thisArg;
// render befor the callback gets asigned to not call the callback at init
this.render();
this.callback = callback;
this.$el.bind('mousedown', $.proxy( this, "start" ) );
},
start: function(event){
event.preventDefault();
this._startPos = event.pageX - this.$el.offset().left;
this.$el.addClass('down');
$(document).bind('mousemove.global', $.proxy( this, "move") );
$(document).one('mouseup', $.proxy( this, "stop") );
},
move: function(event){
var distance = event.pageX - this._startPos;
if(!this._moving && Math.abs(distance) > this._treshhold){
this.$el.addClass('moving');
this._moving = true;
}
if(this._moving){
this._pos = Math.min(0, Math.max(-this.width/2, this._offset + distance));
this.$slider.css('left', this._pos);
}
},
render: function(){
this._offset = this.model[this.toggle] ? -this.width/2 : 0;
this.$slider.css('left', this._offset);
if(this.callback) this.callback();
},
stop: function(event){
this.$el.removeClass('down');
if(this._moving){
this._moving = false;
this.$el.removeClass('moving');
if(this._pos >= -this.width/4){
this.model[this.toggle] = false;
} else {
this.model[this.toggle] = true;
}
} else {
this.model[this.toggle] = !this.model[this.toggle];
}
this.render();
}
};
var slider = {
init: function(el, model){
this.$el = $("#"+el+" ."+model).prev("div.slider");
this.$pointer = this.$el.find('> div:nth-child(2)');
this.$input = this.$el.next('input');
this.max = this.$input.data("max");
this.length = this.$el.width();
this.ease = this.$el.data("easing");
this.style = el;
this.model = model;
this.$el.bind("mousedown", $.proxy( this, "start" ) );
this.$input.change( $.proxy( this, "get" ) );
},
acc: function(x){
return this.ease ? x*x : x;
},
invAcc: function(x){
return this.ease ? Math.sqrt(x) : x;
},
get: function(){
var value = parseInt(this.$input.val());
this.update(value);
},
set: function(value){
this.$input.val(value);
},
update: function(value, position){
this.move(this.toPos(value));
currentStyle[this.style][this.model] = value;
this.move(position || this.toPos(value));
this.set(value);
style[this.style].paint();
},
move: function(x){
this.$pointer.css({ left: x+'px' });
},
toPos: function(value){
var percentage = this.invAcc(value/this.max);
return Math.round(this.length*percentage);
},
toValue: function(position){
var percentage = this.acc(position/this.length);
return Math.round(percentage*this.max);
},
start: function(event){
this.offset = { x: this.$el.offset().left };
this.slide(event);
$(document).bind('mousemove.global', $.proxy( this, "slide" ) );
},
slide: function(event){
event.preventDefault();
var value, position = Math.max(0, Math.min(this.length, event.pageX - this.offset.x));
value = this.toValue(position);
this.update(value, position);
}
};
================================================
FILE: js/universe.js
================================================
var parallelUniverse = {
x: 0,
y: 0,
KAPPA: 4*(Math.SQRT2-1)/3,
roundToHalf: function(value){
// makes the borders crisp
return (value - parseInt(value, 10)) === 0.5 ? value+1 : value + 1.5;
},
draw: function(){
this.x = this.roundToHalf(dimensions.width/2 - currentStyle.width/2);
this.y = this.roundToHalf(dimensions.height/2 - currentStyle.height/2);
pu.clearRect(0,0,dimensions.width,dimensions.height);
this.background();
this.drawCanvases();
this.shadow();
pu.beginPath();
this.rect(pu);
pu.closePath();
this.layerBackground();
this.innerShadow();
this.border();
},
background: function(){
pu.fillStyle = tools.decodeCanvasGradient(
background.background[1].stops, background.background[1].angle, background.background[1].style, pu, 0, 0, dimensions.width, dimensions.height
);
pu.fillRect(0, 0, dimensions.width, dimensions.height);
},
rect: function(ctx){
var br = currentStyle.borderRadius;
if(br.isActive){
for(var i=3; i>=0; i--){
var radiusX, radiusY, unit, percentage;
unit = br.radii[i][1];
if(unit === "%"){
percentage = Math.min(0.5, br.radii[i][0]/100);
radiusY = percentage*currentStyle.height;
radiusX = percentage*currentStyle.width;
} else {
radiusX = radiusY = Math.min(currentStyle.width/2, br.radii[i][0]);
}
switch(i){ // anti-clockwise because of the innerShadow-mask
case 3: // start at left middle; then bottom left
ctx.moveTo(this.x, this.y+currentStyle.height/2);
ctx.lineTo(this.x, this.y+currentStyle.height-radiusY);
ctx.bezierCurveTo(this.x, this.y+currentStyle.height-radiusY+radiusY*this.KAPPA, this.x+(radiusX-radiusX*this.KAPPA), this.y+currentStyle.height, this.x+radiusX, this.y+currentStyle.height);
break;
case 2: // upper right
ctx.lineTo(this.x+currentStyle.width-radiusX, this.y+currentStyle.height);
ctx.bezierCurveTo(this.x+currentStyle.width-radiusX+radiusX*this.KAPPA, this.y+currentStyle.height, this.x+currentStyle.width, this.y+currentStyle.height-radiusY+radiusY*this.KAPPA, this.x+currentStyle.width, this.y+currentStyle.height-radiusY);
break;
case 1: // bottom right
ctx.lineTo(this.x+currentStyle.width, this.y+radiusY);
ctx.bezierCurveTo(this.x+currentStyle.width, this.y+(radiusY-radiusY*this.KAPPA), this.x+currentStyle.width-radiusX+radiusX*this.KAPPA, this.y, this.x+currentStyle.width-radiusX, this.y);
break;
case 0: // upper left and then back to left middle;
ctx.lineTo(this.x+radiusX, this.y);
ctx.bezierCurveTo(this.x+(radiusX-radiusX*this.KAPPA), this.y, this.x, this.y+(radiusY-radiusY*this.KAPPA), this.x, this.y+radiusY);
ctx.lineTo(this.x, this.y+currentStyle.height/2);
break;
}
}
} else {
// outwritten rect anti-clockwise instead of the ctx.rect(x,y,width,height) because of the innerShadow mask
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x, this.y+currentStyle.height);
ctx.lineTo(this.x+currentStyle.width, this.y+currentStyle.height);
ctx.lineTo(this.x+currentStyle.width, this.y);
ctx.lineTo(this.x, this.y);
}
},
drawCanvases: function(){
var $canvases = $workspace.find('canvas.moveable');
$.each($canvases, function(i, canvas){
var $canvas = $(canvas),
offset = $canvas.offset();
pu.drawImage(canvas, offset.left, offset.top);
});
},
shadow: function(){
var sd = currentStyle.dropShadow, dropColor;
if(sd.isActive){
pu.save();
pu.beginPath();
this.rect(pu);
dropColor = sd.color.slice(0);
dropColor.push(sd.opacity/100);
dropColor = tools.toColor(dropColor);
pu.fillStyle = dropColor;
pu.shadowOffsetX = sd.dropX;
pu.shadowOffsetY = sd.dropY;
pu.shadowBlur = sd.blur;
pu.shadowColor = dropColor;
pu.fill();
pu.closePath();
pu.restore();
}
},
innerShadow: function(){
var is = currentStyle.innerShadow, dropColor;
if(is.isActive){
iu.save();
iu.beginPath();
// draw the layer box as negativ area and use normal dropShadow in another universe
// idea by Alistair MacDonald https://gist.github.com/787544
iu.rect(0,0,dimensions.width,dimensions.height);
iu.moveTo(this.x, this.y);
this.rect(iu);
dropColor = is.color.slice(0);
dropColor.push(is.opacity/100);
dropColor = tools.toColor(dropColor);
iu.shadowOffsetX = is.dropX;
iu.shadowOffsetY = is.dropY;
iu.shadowBlur = is.blur;
iu.shadowColor = dropColor;
iu.fill();
iu.closePath();
iu.restore();
// clip the paralell universe temporarily to the layers size (border-radius!)
// and draw the inner shadow from the other universe to the main parallel Universe
pu.save();
pu.beginPath();
this.rect(pu);
pu.closePath();
pu.clip();
pu.drawImage($innerShadowUniverse.get(0), this.x, this.y, currentStyle.width, currentStyle.height, this.x, this.y, currentStyle.width, currentStyle.height);
pu.restore();
iu.clearRect(0,0,dimensions.width,dimensions.height);
}
},
layerBackground: function(){
var bg = currentStyle.background,
tempAngle, tempStops;
if(bg.isActive) {
tempAngle = bg.angle;
tempStops = $.extend(true, [], bg.translucidStops); // no deep copy!
if(bg.hasGlobalLight) bg.angle = currentStyle.globalAngle;
if(bg.isReverse) tempStops = tools.reverseStops(tempStops);
pu.fillStyle = tools.decodeCanvasGradient(
tempStops, tempAngle, bg.style,
pu, this.x, this.y, currentStyle.width, currentStyle.height
);
pu.fill();
}
},
border: function(){
var bd = currentStyle.border, borderColor;
if(bd.isActive){
borderColor = bd.color.slice(0);
borderColor.push(bd.opacity/100);
pu.strokeStyle = tools.toColor(borderColor);
pu.lineWidth = bd.size;
pu.stroke();
}
}
};
================================================
FILE: js/zeroclipboard/ZeroClipboard.as
================================================
package {
// Simple Set Clipboard System
// Author: Joseph Huckaby
import flash.display.Stage;
import flash.display.Sprite;
import flash.display.LoaderInfo;
import flash.display.StageScaleMode;
import flash.events.*;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.external.ExternalInterface;
import flash.system.Security;
import flash.utils.*;
import flash.system.System;
public class ZeroClipboard extends Sprite {
private var id:String = '';
private var button:Sprite;
private var clipText:String = '';
public function ZeroClipboard() {
// constructor, setup event listeners and external interfaces
stage.scaleMode = StageScaleMode.EXACT_FIT;
flash.system.Security.allowDomain("*");
// import flashvars
var flashvars:Object = LoaderInfo( this.root.loaderInfo ).parameters;
id = flashvars.id;
// invisible button covers entire stage
button = new Sprite();
button.buttonMode = true;
button.useHandCursor = true;
button.graphics.beginFill(0xCCFF00);
button.graphics.drawRect(0, 0, Math.floor(flashvars.width), Math.floor(flashvars.height));
button.alpha = 0.0;
addChild(button);
button.addEventListener(MouseEvent.CLICK, clickHandler);
button.addEventListener(MouseEvent.MOUSE_OVER, function(event:Event) {
ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOver', null );
} );
button.addEventListener(MouseEvent.MOUSE_OUT, function(event:Event) {
ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOut', null );
} );
button.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event) {
ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseDown', null );
} );
button.addEventListener(MouseEvent.MOUSE_UP, function(event:Event) {
ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseUp', null );
} );
// external functions
ExternalInterface.addCallback("setHandCursor", setHandCursor);
ExternalInterface.addCallback("setText", setText);
// signal to the browser that we are ready
ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'load', null );
}
public function setText(newText) {
// set the maximum number of files allowed
clipText = newText;
}
public function setHandCursor(enabled:Boolean) {
// control whether the hand cursor is shown on rollover (true)
// or the default arrow cursor (false)
button.useHandCursor = enabled;
}
private function clickHandler(event:Event):void {
// user click copies text to clipboard
// as of flash player 10, this MUST happen from an in-movie flash click event
System.setClipboard( clipText );
ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'complete', clipText );
}
}
}
================================================
FILE: js/zeroclipboard/ZeroClipboard.js
================================================
// Simple Set Clipboard System
// Author: Joseph Huckaby
var ZeroClipboard = {
version: "1.0.7",
clients: {}, // registered upload clients on page, indexed by id
moviePath: 'ZeroClipboard.swf', // URL to movie
nextId: 1, // ID of next movie
$: function(thingy) {
// simple DOM lookup utility function
if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
if (!thingy.addClass) {
// extend element with a few useful methods
thingy.hide = function() { this.style.display = 'none'; };
thingy.show = function() { this.style.display = ''; };
thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
thingy.removeClass = function(name) {
var classes = this.className.split(/\s+/);
var idx = -1;
for (var k = 0; k < classes.length; k++) {
if (classes[k] == name) { idx = k; k = classes.length; }
}
if (idx > -1) {
classes.splice( idx, 1 );
this.className = classes.join(' ');
}
return this;
};
thingy.hasClass = function(name) {
return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
};
}
return thingy;
},
setMoviePath: function(path) {
// set path to ZeroClipboard.swf
this.moviePath = path;
},
dispatch: function(id, eventName, args) {
// receive event from flash movie, send to client
var client = this.clients[id];
if (client) {
client.receiveEvent(eventName, args);
}
},
register: function(id, client) {
// register new client to receive events
this.clients[id] = client;
},
getDOMObjectPosition: function(obj, stopObj) {
// get absolute coordinates for dom element
var info = {
left: 0,
top: 0,
width: obj.width ? obj.width : obj.offsetWidth,
height: obj.height ? obj.height : obj.offsetHeight
};
while (obj && (obj != stopObj)) {
info.left += obj.offsetLeft;
info.top += obj.offsetTop;
obj = obj.offsetParent;
}
return info;
},
Client: function(elem) {
// constructor for new simple upload client
this.handlers = {};
// unique ID
this.id = ZeroClipboard.nextId++;
this.movieId = 'ZeroClipboardMovie_' + this.id;
// register client with singleton to receive flash events
ZeroClipboard.register(this.id, this);
// create movie
if (elem) this.glue(elem);
}
};
ZeroClipboard.Client.prototype = {
id: 0, // unique ID for us
ready: false, // whether movie is ready to receive events or not
movie: null, // reference to movie object
clipText: '', // text to copy to clipboard
handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
cssEffects: true, // enable CSS mouse effects on dom container
handlers: null, // user event handlers
glue: function(elem, appendElem, stylesToAdd) {
// glue to DOM element
// elem can be ID or actual DOM element object
this.domElement = ZeroClipboard.$(elem);
// float just above object, or zIndex 99 if dom element isn't set
var zIndex = 99;
if (this.domElement.style.zIndex) {
zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
}
if (typeof(appendElem) == 'string') {
appendElem = ZeroClipboard.$(appendElem);
}
else if (typeof(appendElem) == 'undefined') {
appendElem = document.getElementsByTagName('body'
gitextract_kja_9fna/
├── .project
├── README.markdown
├── builder.html
├── css/
│ ├── index.css
│ └── style.css
├── index.html
└── js/
├── application.js
├── codebox.js
├── color.js
├── colorpicker.js
├── css.js
├── gradienteditor.js
├── localization.js
├── numbers.js
├── style.js
├── styleStore.js
├── tools.js
├── ui.js
├── universe.js
└── zeroclipboard/
├── ZeroClipboard.as
├── ZeroClipboard.fla
├── ZeroClipboard.js
└── ZeroClipboard.swf
SYMBOL INDEX (11 symbols across 1 files)
FILE: js/application.js
function moveWindow (line 203) | function moveWindow(event){
function resizeLayer (line 207) | function resizeLayer(event, x, y){
function showSlide (line 225) | function showSlide(pos){
function dragenter (line 231) | function dragenter(e) {
function dragleave (line 237) | function dragleave(e) {
function dragover (line 243) | function dragover(e) {
function drop (line 248) | function drop(e) {
function showPickArea (line 291) | function showPickArea(){
function hidePickArea (line 300) | function hidePickArea(){
function pick (line 306) | function pick(event){
function initialise (line 312) | function initialise() {
Condensed preview — 23 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (214K chars).
[
{
"path": ".project",
"chars": 204,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>LayerStyles</name>\n\t<comment></comment>\n\t<projects>\n\t"
},
{
"path": "README.markdown",
"chars": 311,
"preview": "Layer Styles\n============\n\nA HTML5 app for creating CSS3 in a intuitive way.\n\nHighlights\n----------\n\n- Colorpicker can p"
},
{
"path": "builder.html",
"chars": 20308,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <title>Layer S"
},
{
"path": "css/index.css",
"chars": 4693,
"preview": "* { margin: 0; padding: 0; }\nhtml { height: 100%; }\nbody {\n\tfont: 12px/1.4 \"Helvetica Neue\", Helvetica, Arial, sans-seri"
},
{
"path": "css/style.css",
"chars": 30440,
"preview": "* { margin: 0; padding: 0; }\nbody, html { height: 100%; overflow: hidden; }\nbody {\n width: 100%;\n font: 12px/14px "
},
{
"path": "index.html",
"chars": 2850,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n\t<title>Layer Styles<"
},
{
"path": "js/application.js",
"chars": 13470,
"preview": "/*!\n * _ ________ _\n * | | "
},
{
"path": "js/codebox.js",
"chars": 4298,
"preview": "var codeBox = {\n options: {\n visible: true,\n height: 143\n },\n minHeight: 100,\n init: function("
},
{
"path": "js/color.js",
"chars": 2405,
"preview": "var color = {\n hsbFromRgb: function(rgb) {\n r = rgb[0]/255, g = rgb[1]/255, b = rgb[2]/255;\n var max = "
},
{
"path": "js/colorpicker.js",
"chars": 21636,
"preview": "/*\n * LayerStyles\n * http://www.layerstyles.org\n * \n * Copyright (c) 2011 Felix Niklas\n * This scrip"
},
{
"path": "js/css.js",
"chars": 7840,
"preview": "var css = {\n colors: {\n 'rgb(0,0,0)': \"black\",\n 'rgb(255,255,255)': \"white\"\n },\n gradientDirectio"
},
{
"path": "js/gradienteditor.js",
"chars": 19333,
"preview": "var gradienteditor = {\n callback: null,\n thisArg: null,\n changed: false,\n puff: null,\n gradientDimensions"
},
{
"path": "js/localization.js",
"chars": 1901,
"preview": "var localization = {\n en: {\n \"Color\": \"Color\",\n \"Opacity\": \"Opacity\",\n \"Angle\": "
},
{
"path": "js/numbers.js",
"chars": 6669,
"preview": "var numbers = {\n regex: new RegExp(''),\n min: 0,\n max: 0,\n temporaryMode: \"\",\n match: false,\n pressed:"
},
{
"path": "js/style.js",
"chars": 22340,
"preview": "var style = {\n background: {\n elements: {\n \".opacity\": { name: \"opacity\", handle: \"slider\" },\n "
},
{
"path": "js/styleStore.js",
"chars": 7416,
"preview": "var styleStore = {\n styles: [\n { \n name: \"Default Style\", \n style: { }\n },\n "
},
{
"path": "js/tools.js",
"chars": 12477,
"preview": "var tools = {\n options: {\n hex: true\n },\n /**\n * @method averageGradientColor\n * @param fullS"
},
{
"path": "js/ui.js",
"chars": 5606,
"preview": "var pot = {\n init: function(el){\n // el = background, dropShadow, innerShadow\n this.$el = $(\"#\"+el+\" .p"
},
{
"path": "js/universe.js",
"chars": 7166,
"preview": "var parallelUniverse = {\n x: 0,\n y: 0,\n KAPPA: 4*(Math.SQRT2-1)/3,\n roundToHalf: function(value){\n //"
},
{
"path": "js/zeroclipboard/ZeroClipboard.as",
"chars": 2793,
"preview": "package {\n\t// Simple Set Clipboard System\n\t// Author: Joseph Huckaby\n\t\n\timport flash.display.Stage;\n\timport flash.displ"
},
{
"path": "js/zeroclipboard/ZeroClipboard.js",
"chars": 9784,
"preview": "// Simple Set Clipboard System\n// Author: Joseph Huckaby\n\nvar ZeroClipboard = {\n\t\n\tversion: \"1.0.7\",\n\tclients: {}, // re"
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the mrflix/LayerStyles GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 23 files (199.2 KB), approximately 51.9k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.