├── README.md ├── swatches.js ├── generator.js └── dependencies └── colorpicker.js /README.md: -------------------------------------------------------------------------------- 1 | This project has moved to the [CSS3Factory](http://www.css3factory.com) 2 | 3 | See [CSS3Factory Github Project](https://github.com/dgalarza/CSS3Factory) 4 | -------------------------------------------------------------------------------- /swatches.js: -------------------------------------------------------------------------------- 1 | if(typeof cssGradient === 'undefined') { 2 | var cssGradient = {}; 3 | } 4 | 5 | /** 6 | * Color Swatch API for use with Gradient Generator 7 | * cssGradient.swatch provides all functionality related to color 8 | * swatches and their properties including setting the color and position 9 | * of a swatch within a gradient. 10 | * 11 | * This API returns 2 accessor methods, the first for retrieving the 12 | * current palette of swatches, the second to retrieve the currently 13 | * selected swatch. 14 | */ 15 | cssGradient.swatch = (function () { 16 | 17 | // Array Remove - By John Resig (MIT Licensed) 18 | Array.prototype.remove = function(from, to) { 19 | var rest = this.slice((to || from) + 1 || this.length); 20 | this.length = from < 0 ? this.length + from : from; 21 | return this.push.apply(this, rest); 22 | }; 23 | 24 | // Hold our color swatch palette here 25 | var palette = []; 26 | 27 | // Hold a count of how many swatches were created with our pallete for ID names 28 | var swatchCount = 0; 29 | 30 | // Cache the container 31 | var $container; 32 | 33 | // Hold our currently selected swatch ID here 34 | var currentSwatch = 0; 35 | 36 | // Color Format, default to rgb 37 | var colorFormat = 'rgb'; 38 | 39 | // Hold the swatch controls 40 | var $swatchControls = $('#swatch-controls'); 41 | 42 | //Set up the swatch handler 43 | var init = function () { 44 | //Cache our swatch container up front 45 | $container = $('#color-swatches'); 46 | 47 | // Let's see if the user has a preference for another color format 48 | checkCookie(); 49 | 50 | //Set up the click handler for add swatch 51 | $('#add-swatch').click(function(e){ 52 | e.preventDefault(); 53 | createSwatch(); 54 | $('#' + currentSwatch).click(); 55 | }); 56 | 57 | // Set up events for switching color format 58 | $('#color-format').change(function (e) { 59 | var val = $(this).val(); 60 | 61 | colorFormat = val; 62 | setCookie(val); 63 | }); 64 | 65 | // Set up the event handler for keyup detection on manual gradient position 66 | $('#slider-input input[type=text]').bind('keyup', slideInputUpdate); 67 | 68 | // Setup the jQuery live event handler for click events on swatches 69 | $('#color-swatches li.swatch').live('click', swatchClick); 70 | 71 | // Setup the slider with methods relating to swatches 72 | $swatchControls.find('#swatch-slider').slider({ 73 | change : slideChange, 74 | slide : slideChange, 75 | }); 76 | 77 | $swatchControls.find('#remove-trigger').click(removeSwatch); 78 | }; 79 | 80 | /** 81 | * Creates a new color swatch on the page and in our palette. 82 | * 83 | * @param {Object} (Optional) Set of configuration properties for this swatch 84 | */ 85 | var createSwatch = function (config) { 86 | // Clone our template swatch 87 | var $newSwatch = $('#swatch-template').clone(true); 88 | 89 | // Update swatchCount 90 | swatchCount++; 91 | 92 | var swatchID = swatchCount, 93 | paletteLength = palette.length, 94 | lastSwatch = palette[paletteLength - 1]; 95 | 96 | // Setup our new swatch 97 | $newSwatch 98 | .attr('id', 'swatch-' + swatchID) 99 | .attr('rel', 'swatch-' + swatchID) 100 | .removeClass('hide'); 101 | 102 | // Append swatch to page 103 | $container.append($newSwatch); 104 | 105 | // Use a config object if one was sent 106 | if(config) { 107 | setupSwatch('swatch-' + swatchID, config); 108 | } 109 | // If there is a previous swatch, let's progressively update this one 110 | else if(lastSwatch) { 111 | 112 | var newRgb = getUpdatedHue(lastSwatch.rgb); 113 | 114 | var swatchConfig = { 115 | rgb : newRgb, 116 | hex : rgbToHex(newRgb), 117 | position : getNextPosition(lastSwatch.position) 118 | }; 119 | 120 | setupSwatch('swatch-' + swatchID, swatchConfig); 121 | } 122 | // Otherwise, just set up the swatch with the defaults 123 | else { 124 | setupSwatch('swatch-' + swatchID); 125 | } 126 | 127 | // Click the swatch, setting it as the current swatch 128 | $newSwatch.click(); 129 | }; 130 | 131 | /** 132 | * Takes a swatch ID element and set's it up including 133 | * setting up the swatche's start color, position, the slider 134 | * associated with the swatch, etc. 135 | * 136 | * @param {String} | Element ID 137 | * @param {Object} | Configuration parameters for the object (Color and position) 138 | */ 139 | var setupSwatch = function (element, config) { 140 | var config = config || function() { 141 | 142 | var colors = getColorTemplate(); 143 | 144 | return { 145 | 'rgb' : colors.rgb, 146 | 'hex' : colors.hex, 147 | 'position' : 0 148 | } 149 | 150 | }(); 151 | 152 | var $_thisSwatch = $('#' + element); 153 | $_thisSwatch.click(swatchClick); 154 | 155 | //Update our swatch count (simply used for naming conventions) 156 | swatchCount++; 157 | 158 | //Set up a new swatch object 159 | palette.push({ 160 | 'rgb' : config.rgb, 161 | 'hex' : config.hex, 162 | 'id' : element, 163 | 'position' : config.position 164 | }); 165 | 166 | 167 | //Set up the swatches color 168 | $_thisSwatch.find('a').css('background-color', 'rgb(' + config.rgb.r + ',' + config.rgb.g + ',' + config.rgb.b + ')'); 169 | 170 | currentSwatch = palette.length-1; 171 | 172 | // Update the slider 173 | updateSlider(config.position); 174 | }; 175 | 176 | /** 177 | * Click handler for the remove swatch trigger. This removes the swatch 178 | * from the page as well as its entry in the gradients array. 179 | * 180 | * Once it is removed, the gradient sample is updated to show this. 181 | */ 182 | var removeSwatch = function(e) { 183 | e.preventDefault(); 184 | 185 | var nextIndex; 186 | currentSwatch === 0 ? nextIndex = 1 : nextIndex = currentSwatch - 1; 187 | 188 | // Remove the swatch from the page 189 | $('#' + palette[currentSwatch].id).remove(); 190 | 191 | // Remove the swatch from our palette 192 | palette.remove(currentSwatch); 193 | 194 | // Set our current selected swatch after removing this swatch 195 | var nextSwatch = palette[nextIndex]; 196 | if(nextSwatch) $('#' + nextSwatch.id).click(); 197 | }; 198 | 199 | /** 200 | * Handle a swatch click 201 | */ 202 | var swatchClick = function (e) { 203 | e.preventDefault(); 204 | currentSwatch = findSwatch(this.id); 205 | 206 | $container.find('.selected-swatch').removeClass('selected-swatch'); 207 | $(this).addClass('selected-swatch'); 208 | 209 | updateSlider(); 210 | }; 211 | 212 | /** 213 | * Update the slider based on the currently selected swatch 214 | * 215 | */ 216 | var updateSlider = function() { 217 | var _thisSwatch = palette[currentSwatch]; 218 | $('#swatch-slider').slider('option', 'value', _thisSwatch.position); 219 | $('#slider-input input[type=text]').attr('value', _thisSwatch.position); 220 | }; 221 | 222 | /** 223 | * Set the color of the current swatch 224 | * 225 | * @param {String} RGB Color for swatch 226 | * @param {String} HEX Color for swatch 227 | */ 228 | var setColor = function(rgb, hex) { 229 | var current = palette[currentSwatch]; 230 | current.hex = hex; 231 | current.rgb = rgb; 232 | 233 | 234 | $('#' + current.id).find('a').css('background-color', '#' + hex); 235 | }; 236 | 237 | /** 238 | * Set the color position of the swatch in the gradient 239 | * 240 | * @param {String} Swatch ID 241 | * @param {String} Position value 242 | */ 243 | var setPosition = function(swatch, position) { 244 | if(palette[swatch]) { 245 | palette[swatch].position = position; 246 | } 247 | }; 248 | 249 | /** 250 | * Handle the gradient position slider change, updating the 251 | * position of the color in the gradient live, while the user 252 | * adjusts the slider. 253 | */ 254 | var slideChange = function (e, ui) { 255 | if(palette[currentSwatch]) { 256 | palette[currentSwatch].position = ui.value; 257 | $('#slider-input input[type=text]').attr('value', ui.value); 258 | } 259 | }; 260 | 261 | /** 262 | * Handle keyup detection for slider input field so that we can 263 | * update the live gradient sample and CSS code sample as soon 264 | * as the user alters the data. 265 | */ 266 | var slideInputUpdate = function (e) { 267 | e.preventDefault(); 268 | var target = e.target; 269 | var value = this.value; 270 | 271 | //Make sure our value is within the limits before updating 272 | if(value >=0 && value <= 100) { 273 | $('#swatch-slider').slider('option', 'value', value); 274 | palette[currentSwatch].position = value; 275 | } 276 | }; 277 | 278 | /** 279 | * Returns a color template for swatch configuration 280 | * based on color format 281 | */ 282 | var getColorTemplate = function () { 283 | 284 | }; 285 | 286 | /** 287 | * Find a specific swatch in our palette 288 | * 289 | * @param {String} The ID of the string we're looking for 290 | * @return {Int} Index of the swatch if found 291 | * @return {Bool} False if not found 292 | */ 293 | var findSwatch = function(swatchID) { 294 | for(var i=0; i 255) return 255; 331 | 332 | return newColor; 333 | }; 334 | 335 | /** 336 | * Return a new progressive position for the a color 337 | * based off of some previous position value 338 | * 339 | * @param {Int} Previous Color Position 340 | */ 341 | var getNextPosition = function (position) { 342 | var diff = 100 - position; 343 | var delta = Math.ceil(diff * 0.5); 344 | 345 | return delta + position; 346 | 347 | return position; 348 | }; 349 | 350 | /** 351 | * Dumps all of the existing colors in our palette, removing all swatches 352 | */ 353 | var emptyPalette = function () { 354 | // Clear the palette array 355 | palette = []; 356 | 357 | $('#color-swatches .swatch').remove(); 358 | }; 359 | 360 | /** 361 | * Checks to see if the user has a preferred color format 362 | * for gradient colors. If so, set it now. 363 | */ 364 | var checkCookie = function () { 365 | var cookie = document.cookie; 366 | 367 | if(cookie.length === 0) return false; 368 | 369 | var data = cookie.split(';'); 370 | var _this, key, val; 371 | 372 | var whiteList = ['rgb', 'hex']; 373 | 374 | for (var i=0, len = data.length; i < len; i++) { 375 | 376 | _this = data[i].split('='); 377 | 378 | key = _this[0].replace(/^\s+|\s+$/g,""); 379 | val = _this[1]; 380 | 381 | if (key === 'format') { 382 | if (whiteList.indexOf(val) !== -1) { 383 | colorFormat = val; 384 | $('#color-format option[value=' + val + ']')[0].selected = true; 385 | } 386 | else { 387 | setCookie('rgb'); 388 | } 389 | } 390 | } 391 | }; 392 | 393 | /** 394 | * When the user selects a color format, lets remember it 395 | * 396 | * @param {String} Color format 397 | */ 398 | var setCookie = function (format) { 399 | var date = new Date(); 400 | date.setTime(date.getTime() + ( 730 * 24 * 60 * 60 * 1000 )); 401 | 402 | var expires = "; expires=" + date.toGMTString(); 403 | 404 | document.cookie = 'format=' + format + expires + "; path=/"; 405 | }; 406 | 407 | /** 408 | * Takes an RGB object and converts it into a hex string 409 | * 410 | * @param {Object} RGB Colors 411 | */ 412 | var rgbToHex = function(rgb) { 413 | var hex = rgb.b | (rgb.g << 8) | (rgb.r << 16); 414 | return hex.toString(16); 415 | }; 416 | 417 | // Return the Public API for color swatches 418 | return { 419 | 'init' : init, 420 | 421 | // Mutator Methods 422 | 'setColor' : setColor, 423 | 'createSwatch' : createSwatch, 424 | 'emptyPalette' : emptyPalette, 425 | 'rgbToHex' : rgbToHex, 426 | 427 | // Accessor methods 428 | 'getColorFormat' : function () { return colorFormat; }, 429 | 'getCurrentSwatch' : function () { return currentSwatch; }, 430 | 'getPalette' : function () { return palette; }, 431 | 'getPaletteLength' : function () { return palette.length; }, 432 | 'getSwatchColor' : function () { return palette[currentSwatch].rgb; } 433 | }; 434 | 435 | })(); -------------------------------------------------------------------------------- /generator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS3 Webkit Gradient Generator 3 | * 4 | * This script handles all the functionality found on the CSS3 Webkit Gradient Generator. 5 | * The gradient generator is a showcase of webkit CSS gradients and provides a simple 6 | * GUI for a user to create a webkit gradient that can then be used anywhere an image 7 | * could be use in CSS. 8 | * 9 | * The generator is intended to be viewed in a webkit browser in order to get all 10 | * the features, such as the live gradient sampling. Non-webkit browsers will be able to generate 11 | * the webkit code, but will not be able to view a live sample. 12 | * 13 | * @author dgalarza - Damian Galarza 14 | * Released under the MIT License: 15 | * http://www.opensource.org/licenses/mit-license.php 16 | * http://gradients.glrzad.com/ 17 | */ 18 | 19 | $(function () { 20 | 21 | var swatch; 22 | 23 | var vendor_prefixes = [' ', '-o-', '-moz-', '-webkit-', '-ms-', ' ']; 24 | 25 | var generator = { 26 | 27 | /** 28 | * Hold our gradient properties here, setup default values 29 | */ 30 | gradientProps : { 31 | 'type' : 'linear', 32 | 'xStart' : 'left', 33 | 'yStart' : 'bottom', 34 | 'xEnd' : 'left', 35 | 'yEnd' : 'top', 36 | }, 37 | 38 | /** 39 | * Keep track of the select custom option states here 40 | */ 41 | selectStates : { 42 | 'xStart' : false, 43 | 'yStart' : false, 44 | 'xEnd' : false, 45 | 'yEnd' : false 46 | }, 47 | 48 | /** 49 | * Other general, reuseable variables here 50 | */ 51 | sample : $('#sample-btn'), 52 | picker : $('#color-picker'), 53 | gradientString : $('#gradient-css pre'), 54 | 55 | /** 56 | * Let's set everything up 57 | */ 58 | init : function () { 59 | var $selectWrapper = $('.select-wrapper'); 60 | 61 | // Point to the swatch API and initialize it right away 62 | swatch = cssGradient.swatch; 63 | swatch.init(); 64 | 65 | // Create initial radom gradient 66 | randomizer.generateRandomGradient(); 67 | 68 | // Set up our ColorPicker 69 | generator.picker.ColorPicker({ 70 | flat: true, 71 | onChange : generator.retrieveColor, 72 | }) 73 | .ColorPickerSetColor('#23adad') 74 | .mouseup(generator.updateCodeSample); 75 | 76 | // Setup the direction option event handlers 77 | 78 | // Set the jump menu event handlers 79 | $selectWrapper.find('select').change(generator.selectChange); 80 | 81 | // Set up the manual value input handler for gradient direction 82 | $selectWrapper.find('input[type=text]').keyup(generator.selectCustomChange); 83 | 84 | // Update our gradient whenever the slide is used 85 | $('#swatch-slider').bind('slidechange slide', generator.setGradient); 86 | 87 | // Extend the remove swatch click handler to update gradient code on new gradient 88 | $('#remove-trigger').click(generator.setGradient); 89 | 90 | // Bind the slider manual text input key up detection to update gradient on value change 91 | $('#slider-input input[type=text]').bind('keyup', generator.setGradient); 92 | 93 | // Extend add swatch button click handler to update gradient code on new gradient 94 | $('#add-swatch').click(generator.setGradient); 95 | 96 | // On swatch click, set the color picker to the color of the swatch 97 | $('#color-swatches .swatch').live('click', function(){ 98 | var color = swatch.getSwatchColor(); 99 | generator.picker.ColorPickerSetColor(color); 100 | }); 101 | 102 | // Apply our randomize link event 103 | $('#randomize-trigger').click(function (e) { 104 | e.preventDefault(); 105 | swatch.emptyPalette(); 106 | randomizer.generateRandomGradient(); 107 | generator.setGradient(); 108 | }); 109 | 110 | $('#color-format').change(function(e) { 111 | generator.setGradient() 112 | }); 113 | 114 | generator.setGradient(); 115 | 116 | }, 117 | 118 | /** 119 | * Retrieves the color sent from ColorPicker plugin 120 | * and set's the swatch's color accordingly 121 | * 122 | * @param {Object} HSB Color syntax 123 | * @param {String} Hex Color Notation 124 | * @param {Object} RGB Color Syntax 125 | */ 126 | retrieveColor : function (hsb, hex, rgb) { 127 | if(swatch.getPaletteLength() > 0) { 128 | swatch.setColor(rgb, hex); 129 | generator.setGradient(); 130 | } 131 | }, 132 | 133 | /** 134 | * Run's through the gradient's properties and applies 135 | * the gradient to our live button sample and updates the 136 | * gradient string sample 137 | */ 138 | setGradient : function () { 139 | 140 | var linear_gradient = generator.generateLinearGradient(); 141 | var sample = generator.sample[0]; 142 | 143 | var compiled_string = ''; 144 | for (var i = 0, len = vendor_prefixes.length; i < len; i++) { 145 | compiled_string = compiled_string + 'background: ' + vendor_prefixes[i] + linear_gradient + ';'; 146 | } 147 | 148 | compiled_string = compiled_string + 'background: ' + generator.generateWebkitGradient() + ';'; 149 | sample.style.cssText = compiled_string; 150 | 151 | // Update string 152 | generator.updateCodeSample(); 153 | }, 154 | 155 | /** 156 | * Update the code sample for the user 157 | * 158 | **/ 159 | updateCodeSample: function() { 160 | var linear_gradient = generator.generateLinearGradient(); 161 | var $gradientString = generator.gradientString; 162 | 163 | var prefix = 'background-image: '; 164 | var gradientString = 'background-image:' + vendor_prefixes.join(linear_gradient + ";\n" + prefix); 165 | 166 | gradientString = gradientString.slice(0, - (prefix.length + 1)); 167 | 168 | var gProps = generator.gradientProps; 169 | gradientString = gradientString + "\n" + prefix + "-webkit-gradient(\n\t"; 170 | gradientString = gradientString + gProps.type + ",\n\t"; 171 | gradientString = gradientString + generator.fetchGradientStart() + ",\n\t"; 172 | gradientString = gradientString + generator.fetchGradientEnd() + ",\n\t"; 173 | 174 | var gradients = swatch.getPalette(); 175 | var pLength = swatch.getPaletteLength(); 176 | var getColor = generator.getColor; 177 | 178 | var gradient, position; 179 | for (var i = 0; i < pLength; i++) { 180 | 181 | var delimiter = (i === pLength - 1) ? "\n" : ",\n\t"; 182 | 183 | gradient = gradients[i]; 184 | position = gradient.position / 100; 185 | 186 | gradientString = gradientString + "color-stop(" + position + ", " + getColor(gradient) + ")" + delimiter; 187 | } 188 | 189 | gradientString = gradientString + ");"; 190 | 191 | $gradientString.html(gradientString); 192 | }, 193 | 194 | getColor: function(obj) { 195 | var colorFormat = swatch.getColorFormat(); 196 | 197 | var colorString; 198 | if (colorFormat === 'hex') { 199 | colorString = '#' + obj.hex.toUpperCase(); 200 | } 201 | else { 202 | var rgb = obj.rgb; 203 | colorString = 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')'; 204 | } 205 | 206 | return colorString; 207 | }, 208 | 209 | /** 210 | * Generate standarized linear gradient strings 211 | * @example 212 | * linear-gradient(top left, rgb(255,0,0), rgb(150, 0, 0)) 213 | */ 214 | generateLinearGradient : function() { 215 | var gradientProps = generator.gradientProps, 216 | gradientString = gradientProps.type + '-gradient(', 217 | gradientData = ''; 218 | $sample = generator.sample, 219 | gCount = swatch.getPaletteLength(), 220 | palette = swatch.getPalette(); 221 | 222 | if (gradientProps.xStart !== gradientProps.xEnd) { 223 | gradientString = gradientString + gradientProps.xStart + ' '; 224 | } 225 | 226 | if (gradientProps.yStart !== gradientProps.yEnd) { 227 | gradientString = gradientString + gradientProps.yStart; 228 | } 229 | 230 | gradientString = gradientString + ', '; 231 | 232 | var getColor = generator.getColor; 233 | 234 | $.each(palette, function (index, obj) { 235 | 236 | if (index > 0) { 237 | gradientData = gradientData + ' '; 238 | } 239 | 240 | gradientData = gradientData + getColor(obj) + ' ' + obj.position + '%,'; 241 | }); 242 | 243 | gradientString = gradientString + gradientData; 244 | gradientString = gradientString.substr(0, gradientString.length - 1) + ')'; 245 | 246 | return gradientString; 247 | }, 248 | 249 | /** 250 | * Factory for generating Webkit gradient code 251 | */ 252 | generateWebkitGradient : function () { 253 | var gradientProps = generator.gradientProps, 254 | gradientString = '-webkit-gradient(' + gradientProps.type + ',' + generator.fetchGradientStart() + ',' + generator.fetchGradientEnd() + ',', 255 | gradientData = ''; 256 | 257 | var palette = swatch.getPalette(), 258 | pLength = palette.length, 259 | percent, obj; 260 | 261 | for(var i=0; i charMin && pressedKey <= 90) || pressedKey == 32) { 64 | return false; 65 | } 66 | var cal = $(this).parent().parent(); 67 | if (cal.data('colorpicker').livePreview === true) { 68 | change.apply(this); 69 | } 70 | }, 71 | change = function (ev) { 72 | var cal = $(this).parent().parent(), col; 73 | if (this.parentNode.className.indexOf('_hex') > 0) { 74 | cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value)); 75 | } else if (this.parentNode.className.indexOf('_hsb') > 0) { 76 | cal.data('colorpicker').color = col = fixHSB({ 77 | h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10), 78 | s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10), 79 | b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10) 80 | }); 81 | } else { 82 | cal.data('colorpicker').color = col = RGBToHSB(fixRGB({ 83 | r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10), 84 | g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10), 85 | b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10) 86 | })); 87 | } 88 | if (ev) { 89 | fillRGBFields(col, cal.get(0)); 90 | fillHexFields(col, cal.get(0)); 91 | fillHSBFields(col, cal.get(0)); 92 | } 93 | setSelector(col, cal.get(0)); 94 | setHue(col, cal.get(0)); 95 | setNewColor(col, cal.get(0)); 96 | cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]); 97 | }, 98 | blur = function (ev) { 99 | var cal = $(this).parent().parent(); 100 | cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus'); 101 | }, 102 | focus = function () { 103 | charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65; 104 | $(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus'); 105 | $(this).parent().addClass('colorpicker_focus'); 106 | }, 107 | downIncrement = function (ev) { 108 | var field = $(this).parent().find('input').focus(); 109 | var current = { 110 | el: $(this).parent().addClass('colorpicker_slider'), 111 | max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255), 112 | y: ev.pageY, 113 | field: field, 114 | val: parseInt(field.val(), 10), 115 | preview: $(this).parent().parent().data('colorpicker').livePreview 116 | }; 117 | $(document).bind('mouseup', current, upIncrement); 118 | $(document).bind('mousemove', current, moveIncrement); 119 | }, 120 | moveIncrement = function (ev) { 121 | ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10)))); 122 | if (ev.data.preview) { 123 | change.apply(ev.data.field.get(0), [true]); 124 | } 125 | return false; 126 | }, 127 | upIncrement = function (ev) { 128 | change.apply(ev.data.field.get(0), [true]); 129 | ev.data.el.removeClass('colorpicker_slider').find('input').focus(); 130 | $(document).unbind('mouseup', upIncrement); 131 | $(document).unbind('mousemove', moveIncrement); 132 | return false; 133 | }, 134 | downHue = function (ev) { 135 | var current = { 136 | cal: $(this).parent(), 137 | y: $(this).offset().top 138 | }; 139 | current.preview = current.cal.data('colorpicker').livePreview; 140 | $(document).bind('mouseup', current, upHue); 141 | $(document).bind('mousemove', current, moveHue); 142 | }, 143 | moveHue = function (ev) { 144 | change.apply( 145 | ev.data.cal.data('colorpicker') 146 | .fields 147 | .eq(4) 148 | .val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10)) 149 | .get(0), 150 | [ev.data.preview] 151 | ); 152 | return false; 153 | }, 154 | upHue = function (ev) { 155 | fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); 156 | fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); 157 | $(document).unbind('mouseup', upHue); 158 | $(document).unbind('mousemove', moveHue); 159 | return false; 160 | }, 161 | downSelector = function (ev) { 162 | var current = { 163 | cal: $(this).parent(), 164 | pos: $(this).offset() 165 | }; 166 | current.preview = current.cal.data('colorpicker').livePreview; 167 | $(document).bind('mouseup', current, upSelector); 168 | $(document).bind('mousemove', current, moveSelector); 169 | }, 170 | moveSelector = function (ev) { 171 | change.apply( 172 | ev.data.cal.data('colorpicker') 173 | .fields 174 | .eq(6) 175 | .val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10)) 176 | .end() 177 | .eq(5) 178 | .val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10)) 179 | .get(0), 180 | [ev.data.preview] 181 | ); 182 | return false; 183 | }, 184 | upSelector = function (ev) { 185 | fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); 186 | fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); 187 | $(document).unbind('mouseup', upSelector); 188 | $(document).unbind('mousemove', moveSelector); 189 | return false; 190 | }, 191 | enterSubmit = function (ev) { 192 | $(this).addClass('colorpicker_focus'); 193 | }, 194 | leaveSubmit = function (ev) { 195 | $(this).removeClass('colorpicker_focus'); 196 | }, 197 | clickSubmit = function (ev) { 198 | var cal = $(this).parent(); 199 | var col = cal.data('colorpicker').color; 200 | cal.data('colorpicker').origColor = col; 201 | setCurrentColor(col, cal.get(0)); 202 | cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el); 203 | }, 204 | show = function (ev) { 205 | var cal = $('#' + $(this).data('colorpickerId')); 206 | cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]); 207 | var pos = $(this).offset(); 208 | var viewPort = getViewport(); 209 | var top = pos.top + this.offsetHeight; 210 | var left = pos.left; 211 | if (top + 176 > viewPort.t + viewPort.h) { 212 | top -= this.offsetHeight + 176; 213 | } 214 | if (left + 356 > viewPort.l + viewPort.w) { 215 | left -= 356; 216 | } 217 | cal.css({left: left + 'px', top: top + 'px'}); 218 | if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) { 219 | cal.show(); 220 | } 221 | $(document).bind('mousedown', {cal: cal}, hide); 222 | return false; 223 | }, 224 | hide = function (ev) { 225 | if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) { 226 | if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) { 227 | ev.data.cal.hide(); 228 | } 229 | $(document).unbind('mousedown', hide); 230 | } 231 | }, 232 | isChildOf = function(parentEl, el, container) { 233 | if (parentEl == el) { 234 | return true; 235 | } 236 | if (parentEl.contains) { 237 | return parentEl.contains(el); 238 | } 239 | if ( parentEl.compareDocumentPosition ) { 240 | return !!(parentEl.compareDocumentPosition(el) & 16); 241 | } 242 | var prEl = el.parentNode; 243 | while(prEl && prEl != container) { 244 | if (prEl == parentEl) 245 | return true; 246 | prEl = prEl.parentNode; 247 | } 248 | return false; 249 | }, 250 | getViewport = function () { 251 | var m = document.compatMode == 'CSS1Compat'; 252 | return { 253 | l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft), 254 | t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop), 255 | w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth), 256 | h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight) 257 | }; 258 | }, 259 | fixHSB = function (hsb) { 260 | return { 261 | h: Math.min(360, Math.max(0, hsb.h)), 262 | s: Math.min(100, Math.max(0, hsb.s)), 263 | b: Math.min(100, Math.max(0, hsb.b)) 264 | }; 265 | }, 266 | fixRGB = function (rgb) { 267 | return { 268 | r: Math.min(255, Math.max(0, rgb.r)), 269 | g: Math.min(255, Math.max(0, rgb.g)), 270 | b: Math.min(255, Math.max(0, rgb.b)) 271 | }; 272 | }, 273 | fixHex = function (hex) { 274 | var len = 6 - hex.length; 275 | if (len > 0) { 276 | var o = []; 277 | for (var i=0; i -1) ? hex.substring(1) : hex), 16); 287 | return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)}; 288 | }, 289 | HexToHSB = function (hex) { 290 | return RGBToHSB(HexToRGB(hex)); 291 | }, 292 | RGBToHSB = function (rgb) { 293 | var hsb = { 294 | h: 0, 295 | s: 0, 296 | b: 0 297 | }; 298 | var min = Math.min(rgb.r, rgb.g, rgb.b); 299 | var max = Math.max(rgb.r, rgb.g, rgb.b); 300 | var delta = max - min; 301 | hsb.b = max; 302 | if (max != 0) { 303 | 304 | } 305 | hsb.s = max != 0 ? 255 * delta / max : 0; 306 | if (hsb.s != 0) { 307 | if (rgb.r == max) { 308 | hsb.h = (rgb.g - rgb.b) / delta; 309 | } else if (rgb.g == max) { 310 | hsb.h = 2 + (rgb.b - rgb.r) / delta; 311 | } else { 312 | hsb.h = 4 + (rgb.r - rgb.g) / delta; 313 | } 314 | } else { 315 | hsb.h = -1; 316 | } 317 | hsb.h *= 60; 318 | if (hsb.h < 0) { 319 | hsb.h += 360; 320 | } 321 | hsb.s *= 100/255; 322 | hsb.b *= 100/255; 323 | return hsb; 324 | }, 325 | HSBToRGB = function (hsb) { 326 | var rgb = {}; 327 | var h = Math.round(hsb.h); 328 | var s = Math.round(hsb.s*255/100); 329 | var v = Math.round(hsb.b*255/100); 330 | if(s == 0) { 331 | rgb.r = rgb.g = rgb.b = v; 332 | } else { 333 | var t1 = v; 334 | var t2 = (255-s)*v/255; 335 | var t3 = (t1-t2)*(h%60)/60; 336 | if(h==360) h = 0; 337 | if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3} 338 | else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3} 339 | else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3} 340 | else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3} 341 | else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3} 342 | else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3} 343 | else {rgb.r=0; rgb.g=0; rgb.b=0} 344 | } 345 | return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)}; 346 | }, 347 | RGBToHex = function (rgb) { 348 | var hex = [ 349 | rgb.r.toString(16), 350 | rgb.g.toString(16), 351 | rgb.b.toString(16) 352 | ]; 353 | $.each(hex, function (nr, val) { 354 | if (val.length == 1) { 355 | hex[nr] = '0' + val; 356 | } 357 | }); 358 | return hex.join(''); 359 | }, 360 | HSBToHex = function (hsb) { 361 | return RGBToHex(HSBToRGB(hsb)); 362 | }, 363 | restoreOriginal = function () { 364 | var cal = $(this).parent(); 365 | var col = cal.data('colorpicker').origColor; 366 | cal.data('colorpicker').color = col; 367 | fillRGBFields(col, cal.get(0)); 368 | fillHexFields(col, cal.get(0)); 369 | fillHSBFields(col, cal.get(0)); 370 | setSelector(col, cal.get(0)); 371 | setHue(col, cal.get(0)); 372 | setNewColor(col, cal.get(0)); 373 | }; 374 | return { 375 | init: function (opt) { 376 | opt = $.extend({}, defaults, opt||{}); 377 | if (typeof opt.color == 'string') { 378 | opt.color = HexToHSB(opt.color); 379 | } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) { 380 | opt.color = RGBToHSB(opt.color); 381 | } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) { 382 | opt.color = fixHSB(opt.color); 383 | } else { 384 | return this; 385 | } 386 | return this.each(function () { 387 | if (!$(this).data('colorpickerId')) { 388 | var options = $.extend({}, opt); 389 | options.origColor = opt.color; 390 | var id = 'collorpicker_' + parseInt(Math.random() * 1000); 391 | $(this).data('colorpickerId', id); 392 | var cal = $(tpl).attr('id', id); 393 | if (options.flat) { 394 | cal.appendTo(this).show(); 395 | } else { 396 | cal.appendTo(document.body); 397 | } 398 | options.fields = cal 399 | .find('input') 400 | .bind('keyup', keyDown) 401 | .bind('change', change) 402 | .bind('blur', blur) 403 | .bind('focus', focus); 404 | cal 405 | .find('span').bind('mousedown', downIncrement).end() 406 | .find('>div.colorpicker_current_color').bind('click', restoreOriginal); 407 | options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector); 408 | options.selectorIndic = options.selector.find('div div'); 409 | options.el = this; 410 | options.hue = cal.find('div.colorpicker_hue div'); 411 | cal.find('div.colorpicker_hue').bind('mousedown', downHue); 412 | options.newColor = cal.find('div.colorpicker_new_color'); 413 | options.currentColor = cal.find('div.colorpicker_current_color'); 414 | cal.data('colorpicker', options); 415 | cal.find('div.colorpicker_submit') 416 | .bind('mouseenter', enterSubmit) 417 | .bind('mouseleave', leaveSubmit) 418 | .bind('click', clickSubmit); 419 | fillRGBFields(options.color, cal.get(0)); 420 | fillHSBFields(options.color, cal.get(0)); 421 | fillHexFields(options.color, cal.get(0)); 422 | setHue(options.color, cal.get(0)); 423 | setSelector(options.color, cal.get(0)); 424 | setCurrentColor(options.color, cal.get(0)); 425 | setNewColor(options.color, cal.get(0)); 426 | if (options.flat) { 427 | cal.css({ 428 | position: 'relative', 429 | display: 'block' 430 | }); 431 | } else { 432 | $(this).bind(options.eventName, show); 433 | } 434 | } 435 | }); 436 | }, 437 | showPicker: function() { 438 | return this.each( function () { 439 | if ($(this).data('colorpickerId')) { 440 | show.apply(this); 441 | } 442 | }); 443 | }, 444 | hidePicker: function() { 445 | return this.each( function () { 446 | if ($(this).data('colorpickerId')) { 447 | $('#' + $(this).data('colorpickerId')).hide(); 448 | } 449 | }); 450 | }, 451 | setColor: function(col) { 452 | if (typeof col == 'string') { 453 | col = HexToHSB(col); 454 | } else if (col.r != undefined && col.g != undefined && col.b != undefined) { 455 | col = RGBToHSB(col); 456 | } else if (col.h != undefined && col.s != undefined && col.b != undefined) { 457 | col = fixHSB(col); 458 | } else { 459 | return this; 460 | } 461 | return this.each(function(){ 462 | if ($(this).data('colorpickerId')) { 463 | var cal = $('#' + $(this).data('colorpickerId')); 464 | cal.data('colorpicker').color = col; 465 | cal.data('colorpicker').origColor = col; 466 | fillRGBFields(col, cal.get(0)); 467 | fillHSBFields(col, cal.get(0)); 468 | fillHexFields(col, cal.get(0)); 469 | setHue(col, cal.get(0)); 470 | setSelector(col, cal.get(0)); 471 | setCurrentColor(col, cal.get(0)); 472 | setNewColor(col, cal.get(0)); 473 | } 474 | }); 475 | } 476 | }; 477 | }(); 478 | $.fn.extend({ 479 | ColorPicker: ColorPicker.init, 480 | ColorPickerHide: ColorPicker.hidePicker, 481 | ColorPickerShow: ColorPicker.showPicker, 482 | ColorPickerSetColor: ColorPicker.setColor 483 | }); 484 | })(jQuery) --------------------------------------------------------------------------------