-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathswatches.js
435 lines (351 loc) · 10.6 KB
/
swatches.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
if(typeof cssGradient === 'undefined') {
var cssGradient = {};
}
/**
* Color Swatch API for use with Gradient Generator
* cssGradient.swatch provides all functionality related to color
* swatches and their properties including setting the color and position
* of a swatch within a gradient.
*
* This API returns 2 accessor methods, the first for retrieving the
* current palette of swatches, the second to retrieve the currently
* selected swatch.
*/
cssGradient.swatch = (function () {
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
// Hold our color swatch palette here
var palette = [];
// Hold a count of how many swatches were created with our pallete for ID names
var swatchCount = 0;
// Cache the container
var $container;
// Hold our currently selected swatch ID here
var currentSwatch = 0;
// Color Format, default to rgb
var colorFormat = 'rgb';
// Hold the swatch controls
var $swatchControls = $('#swatch-controls');
//Set up the swatch handler
var init = function () {
//Cache our swatch container up front
$container = $('#color-swatches');
// Let's see if the user has a preference for another color format
checkCookie();
//Set up the click handler for add swatch
$('#add-swatch').click(function(e){
e.preventDefault();
createSwatch();
$('#' + currentSwatch).click();
});
// Set up events for switching color format
$('#color-format').change(function (e) {
var val = $(this).val();
colorFormat = val;
setCookie(val);
});
// Set up the event handler for keyup detection on manual gradient position
$('#slider-input input[type=text]').bind('keyup', slideInputUpdate);
// Setup the jQuery live event handler for click events on swatches
$('#color-swatches li.swatch').live('click', swatchClick);
// Setup the slider with methods relating to swatches
$swatchControls.find('#swatch-slider').slider({
change : slideChange,
slide : slideChange,
});
$swatchControls.find('#remove-trigger').click(removeSwatch);
};
/**
* Creates a new color swatch on the page and in our palette.
*
* @param {Object} (Optional) Set of configuration properties for this swatch
*/
var createSwatch = function (config) {
// Clone our template swatch
var $newSwatch = $('#swatch-template').clone(true);
// Update swatchCount
swatchCount++;
var swatchID = swatchCount,
paletteLength = palette.length,
lastSwatch = palette[paletteLength - 1];
// Setup our new swatch
$newSwatch
.attr('id', 'swatch-' + swatchID)
.attr('rel', 'swatch-' + swatchID)
.removeClass('hide');
// Append swatch to page
$container.append($newSwatch);
// Use a config object if one was sent
if(config) {
setupSwatch('swatch-' + swatchID, config);
}
// If there is a previous swatch, let's progressively update this one
else if(lastSwatch) {
var newRgb = getUpdatedHue(lastSwatch.rgb);
var swatchConfig = {
rgb : newRgb,
hex : rgbToHex(newRgb),
position : getNextPosition(lastSwatch.position)
};
setupSwatch('swatch-' + swatchID, swatchConfig);
}
// Otherwise, just set up the swatch with the defaults
else {
setupSwatch('swatch-' + swatchID);
}
// Click the swatch, setting it as the current swatch
$newSwatch.click();
};
/**
* Takes a swatch ID element and set's it up including
* setting up the swatche's start color, position, the slider
* associated with the swatch, etc.
*
* @param {String} | Element ID
* @param {Object} | Configuration parameters for the object (Color and position)
*/
var setupSwatch = function (element, config) {
var config = config || function() {
var colors = getColorTemplate();
return {
'rgb' : colors.rgb,
'hex' : colors.hex,
'position' : 0
}
}();
var $_thisSwatch = $('#' + element);
$_thisSwatch.click(swatchClick);
//Update our swatch count (simply used for naming conventions)
swatchCount++;
//Set up a new swatch object
palette.push({
'rgb' : config.rgb,
'hex' : config.hex,
'id' : element,
'position' : config.position
});
//Set up the swatches color
$_thisSwatch.find('a').css('background-color', 'rgb(' + config.rgb.r + ',' + config.rgb.g + ',' + config.rgb.b + ')');
currentSwatch = palette.length-1;
// Update the slider
updateSlider(config.position);
};
/**
* Click handler for the remove swatch trigger. This removes the swatch
* from the page as well as its entry in the gradients array.
*
* Once it is removed, the gradient sample is updated to show this.
*/
var removeSwatch = function(e) {
e.preventDefault();
var nextIndex;
currentSwatch === 0 ? nextIndex = 1 : nextIndex = currentSwatch - 1;
// Remove the swatch from the page
$('#' + palette[currentSwatch].id).remove();
// Remove the swatch from our palette
palette.remove(currentSwatch);
// Set our current selected swatch after removing this swatch
var nextSwatch = palette[nextIndex];
if(nextSwatch) $('#' + nextSwatch.id).click();
};
/**
* Handle a swatch click
*/
var swatchClick = function (e) {
e.preventDefault();
currentSwatch = findSwatch(this.id);
$container.find('.selected-swatch').removeClass('selected-swatch');
$(this).addClass('selected-swatch');
updateSlider();
};
/**
* Update the slider based on the currently selected swatch
*
*/
var updateSlider = function() {
var _thisSwatch = palette[currentSwatch];
$('#swatch-slider').slider('option', 'value', _thisSwatch.position);
$('#slider-input input[type=text]').attr('value', _thisSwatch.position);
};
/**
* Set the color of the current swatch
*
* @param {String} RGB Color for swatch
* @param {String} HEX Color for swatch
*/
var setColor = function(rgb, hex) {
var current = palette[currentSwatch];
current.hex = hex;
current.rgb = rgb;
$('#' + current.id).find('a').css('background-color', '#' + hex);
};
/**
* Set the color position of the swatch in the gradient
*
* @param {String} Swatch ID
* @param {String} Position value
*/
var setPosition = function(swatch, position) {
if(palette[swatch]) {
palette[swatch].position = position;
}
};
/**
* Handle the gradient position slider change, updating the
* position of the color in the gradient live, while the user
* adjusts the slider.
*/
var slideChange = function (e, ui) {
if(palette[currentSwatch]) {
palette[currentSwatch].position = ui.value;
$('#slider-input input[type=text]').attr('value', ui.value);
}
};
/**
* Handle keyup detection for slider input field so that we can
* update the live gradient sample and CSS code sample as soon
* as the user alters the data.
*/
var slideInputUpdate = function (e) {
e.preventDefault();
var target = e.target;
var value = this.value;
//Make sure our value is within the limits before updating
if(value >=0 && value <= 100) {
$('#swatch-slider').slider('option', 'value', value);
palette[currentSwatch].position = value;
}
};
/**
* Returns a color template for swatch configuration
* based on color format
*/
var getColorTemplate = function () {
};
/**
* Find a specific swatch in our palette
*
* @param {String} The ID of the string we're looking for
* @return {Int} Index of the swatch if found
* @return {Bool} False if not found
*/
var findSwatch = function(swatchID) {
for(var i=0; i<palette.length; i++) {
if(palette[i].id === swatchID) return i;
}
return false;
};
/**
* Take a color code and get a darker color
*
* @param {Object} Some color object to build from
* @return {Object} Updated Color Object
*/
var getUpdatedHue = function (color) {
return {
'r' : nextInRange(color.r),
'g' : nextInRange(color.g),
'b' : nextInRange(color.b)
};
};
/**
* Get the next RGB value based on a previous value
* passed in.
*
* @param {Int} The value for the RGB segment
* @return {Int} Increased color value
*/
var nextInRange = function (color) {
if(color === 0) {
color++;
}
var delta = Math.ceil(255 / color) / 10;
var newColor = Math.ceil(delta * color) + color;
if(newColor > 255) return 255;
return newColor;
};
/**
* Return a new progressive position for the a color
* based off of some previous position value
*
* @param {Int} Previous Color Position
*/
var getNextPosition = function (position) {
var diff = 100 - position;
var delta = Math.ceil(diff * 0.5);
return delta + position;
return position;
};
/**
* Dumps all of the existing colors in our palette, removing all swatches
*/
var emptyPalette = function () {
// Clear the palette array
palette = [];
$('#color-swatches .swatch').remove();
};
/**
* Checks to see if the user has a preferred color format
* for gradient colors. If so, set it now.
*/
var checkCookie = function () {
var cookie = document.cookie;
if(cookie.length === 0) return false;
var data = cookie.split(';');
var _this, key, val;
var whiteList = ['rgb', 'hex'];
for (var i=0, len = data.length; i < len; i++) {
_this = data[i].split('=');
key = _this[0].replace(/^\s+|\s+$/g,"");
val = _this[1];
if (key === 'format') {
if (whiteList.indexOf(val) !== -1) {
colorFormat = val;
$('#color-format option[value=' + val + ']')[0].selected = true;
}
else {
setCookie('rgb');
}
}
}
};
/**
* When the user selects a color format, lets remember it
*
* @param {String} Color format
*/
var setCookie = function (format) {
var date = new Date();
date.setTime(date.getTime() + ( 730 * 24 * 60 * 60 * 1000 ));
var expires = "; expires=" + date.toGMTString();
document.cookie = 'format=' + format + expires + "; path=/";
};
/**
* Takes an RGB object and converts it into a hex string
*
* @param {Object} RGB Colors
*/
var rgbToHex = function(rgb) {
var hex = rgb.b | (rgb.g << 8) | (rgb.r << 16);
return hex.toString(16);
};
// Return the Public API for color swatches
return {
'init' : init,
// Mutator Methods
'setColor' : setColor,
'createSwatch' : createSwatch,
'emptyPalette' : emptyPalette,
'rgbToHex' : rgbToHex,
// Accessor methods
'getColorFormat' : function () { return colorFormat; },
'getCurrentSwatch' : function () { return currentSwatch; },
'getPalette' : function () { return palette; },
'getPaletteLength' : function () { return palette.length; },
'getSwatchColor' : function () { return palette[currentSwatch].rgb; }
};
})();