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
================================================
LayerStyles
================================================
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
================================================
Layer Styles
Layer Style
Drop Shadow
Inner Shadow
Background
Border
Border Radius
Colorpicker
================================================
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
================================================
Layer Styles
Unfortunately your browser doesn't support the following requirements:
Javascript enabled
Native JSON
CSS Background Gradients
Border Radius
HTML5 Canvas
HTML5 Flexbox
RGB Alpha-Channel
Box Shadows
Please update your browser.
================================================
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 = $(""),
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(/
/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) + ";
" : "";
// 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 + ";
";
}
}
}
// add gradient
if(currentStyle.background.isActive){
this.code += "background-image: " + css.drawGradient(currentStyle) + ";
";
}
// add dropShadow and innerShadow
if(currentStyle.dropShadow.isActive || currentStyle.innerShadow.isActive){
this.code += "box-shadow: " + css.boxShadow(currentStyle) + ";
";
}
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')
.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');
for(var i = 0, length = this.swatches.length; i 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')
.css({ 'left': position+'%' })
.bind({
mousedown: $.proxy( this, "select" ),
dblclick: $.proxy( this, "pick" )
})
.append($(''))
.append($('')
.append($('').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 $('')
.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 $('')
.css({ 'left': position+'%' })
.attr({
'data-color': JSON.stringify(rgb),
'data-percentage': position
})
.bind({
mousedown: $.proxy( this, "selectPicker" ),
dblclick: $.proxy( this, "startPicking" )
})
.append($(''))
.append($('')
.append($('').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 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 (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 = $('').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 $('')
.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 = $('');
for(var i=0,length = this.currentGradient.stops.length; i [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 = $('')
.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= 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')
.attr({ 'title': name, 'data-pos': pos })
.bind('mousedown', { self : this }, styleStore.select )
.append( $('').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 [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 [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 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')[0];
}
// find X/Y position of domElement
var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem);
// create floating DIV above element
this.div = document.createElement('div');
var style = this.div.style;
style.position = 'absolute';
style.left = '' + box.left + 'px';
style.top = '' + box.top + 'px';
style.width = '' + box.width + 'px';
style.height = '' + box.height + 'px';
style.zIndex = zIndex;
if (typeof(stylesToAdd) == 'object') {
for (addedStyle in stylesToAdd) {
style[addedStyle] = stylesToAdd[addedStyle];
}
}
// style.backgroundColor = '#f00'; // debug
appendElem.appendChild(this.div);
this.div.innerHTML = this.getHTML( box.width, box.height );
},
getHTML: function(width, height) {
// return HTML for movie
var html = '';
var flashvars = 'id=' + this.id +
'&width=' + width +
'&height=' + height;
if (navigator.userAgent.match(/MSIE/)) {
// IE gets an OBJECT tag
var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
html += '';
}
else {
// all other browsers get an EMBED tag
html += '';
}
return html;
},
hide: function() {
// temporarily hide floater offscreen
if (this.div) {
this.div.style.left = '-2000px';
}
},
show: function() {
// show ourselves after a call to hide()
this.reposition();
},
destroy: function() {
// destroy control and floater
if (this.domElement && this.div) {
this.hide();
this.div.innerHTML = '';
var body = document.getElementsByTagName('body')[0];
try { body.removeChild( this.div ); } catch(e) {;}
this.domElement = null;
this.div = null;
}
},
reposition: function(elem) {
// reposition our floating div, optionally to new container
// warning: container CANNOT change size, only position
if (elem) {
this.domElement = ZeroClipboard.$(elem);
if (!this.domElement) this.hide();
}
if (this.domElement && this.div) {
var box = ZeroClipboard.getDOMObjectPosition(this.domElement);
var style = this.div.style;
style.left = '' + box.left + 'px';
style.top = '' + box.top + 'px';
}
},
setText: function(newText) {
// set text to be copied to clipboard
this.clipText = newText;
if (this.ready) this.movie.setText(newText);
},
addEventListener: function(eventName, func) {
// add user event listener for event
// event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
eventName = eventName.toString().toLowerCase().replace(/^on/, '');
if (!this.handlers[eventName]) this.handlers[eventName] = [];
this.handlers[eventName].push(func);
},
setHandCursor: function(enabled) {
// enable hand cursor (true), or default arrow cursor (false)
this.handCursorEnabled = enabled;
if (this.ready) this.movie.setHandCursor(enabled);
},
setCSSEffects: function(enabled) {
// enable or disable CSS effects on DOM container
this.cssEffects = !!enabled;
},
receiveEvent: function(eventName, args) {
// receive event from flash
eventName = eventName.toString().toLowerCase().replace(/^on/, '');
// special behavior for certain events
switch (eventName) {
case 'load':
// movie claims it is ready, but in IE this isn't always the case...
// bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
this.movie = document.getElementById(this.movieId);
if (!this.movie) {
var self = this;
setTimeout( function() { self.receiveEvent('load', null); }, 1 );
return;
}
// firefox on pc needs a "kick" in order to set these in certain cases
if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
var self = this;
setTimeout( function() { self.receiveEvent('load', null); }, 100 );
this.ready = true;
return;
}
this.ready = true;
this.movie.setText( this.clipText );
this.movie.setHandCursor( this.handCursorEnabled );
break;
case 'mouseover':
if (this.domElement && this.cssEffects) {
this.domElement.addClass('hover');
if (this.recoverActive) this.domElement.addClass('active');
}
break;
case 'mouseout':
if (this.domElement && this.cssEffects) {
this.recoverActive = false;
if (this.domElement.hasClass('active')) {
this.domElement.removeClass('active');
this.recoverActive = true;
}
this.domElement.removeClass('hover');
}
break;
case 'mousedown':
if (this.domElement && this.cssEffects) {
this.domElement.addClass('active');
}
break;
case 'mouseup':
if (this.domElement && this.cssEffects) {
this.domElement.removeClass('active');
this.recoverActive = false;
}
break;
} // switch eventName
if (this.handlers[eventName]) {
for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
var func = this.handlers[eventName][idx];
if (typeof(func) == 'function') {
// actual function reference
func(this, args);
}
else if ((typeof(func) == 'object') && (func.length == 2)) {
// PHP style object + method, i.e. [myObject, 'myMethod']
func[0][ func[1] ](this, args);
}
else if (typeof(func) == 'string') {
// name of function
window[func](this, args);
}
} // foreach event handler defined
} // user defined handler for event
}
};