root / drupal7 / modules / color / color.js @ 8be7bf84
1 |
/**
|
---|---|
2 |
* @file
|
3 |
* Attaches the behaviors for the Color module.
|
4 |
*/
|
5 |
|
6 |
(function ($) { |
7 |
|
8 |
Drupal.behaviors.color = { |
9 |
attach: function (context, settings) { |
10 |
var i, j, colors, field_name;
|
11 |
// This behavior attaches by ID, so is only valid once on a page.
|
12 |
var form = $('#system-theme-settings .color-form', context).once('color'); |
13 |
if (form.length == 0) { |
14 |
return;
|
15 |
} |
16 |
var inputs = [];
|
17 |
var hooks = [];
|
18 |
var locks = [];
|
19 |
var focused = null; |
20 |
|
21 |
// Add Farbtastic.
|
22 |
$(form).prepend('<div id="placeholder"></div>').addClass('color-processed'); |
23 |
var farb = $.farbtastic('#placeholder'); |
24 |
|
25 |
// Decode reference colors to HSL.
|
26 |
var reference = settings.color.reference;
|
27 |
for (i in reference) { |
28 |
reference[i] = farb.RGBToHSL(farb.unpack(reference[i])); |
29 |
} |
30 |
|
31 |
// Build a preview.
|
32 |
var height = [];
|
33 |
var width = [];
|
34 |
// Loop through all defined gradients.
|
35 |
for (i in settings.gradients) { |
36 |
// Add element to display the gradient.
|
37 |
$('#preview').once('color').append('<div id="gradient-' + i + '"></div>'); |
38 |
var gradient = $('#preview #gradient-' + i); |
39 |
// Add height of current gradient to the list (divided by 10).
|
40 |
height.push(parseInt(gradient.css('height'), 10) / 10); |
41 |
// Add width of current gradient to the list (divided by 10).
|
42 |
width.push(parseInt(gradient.css('width'), 10) / 10); |
43 |
// Add rows (or columns for horizontal gradients).
|
44 |
// Each gradient line should have a height (or width for horizontal
|
45 |
// gradients) of 10px (because we divided the height/width by 10 above).
|
46 |
for (j = 0; j < (settings.gradients[i]['direction'] == 'vertical' ? height[i] : width[i]); ++j) { |
47 |
gradient.append('<div class="gradient-line"></div>');
|
48 |
} |
49 |
} |
50 |
|
51 |
// Fix preview background in IE6.
|
52 |
if (navigator.appVersion.match(/MSIE [0-6]\./)) { |
53 |
var e = $('#preview #img')[0]; |
54 |
var image = e.currentStyle.backgroundImage;
|
55 |
e.style.backgroundImage = 'none';
|
56 |
e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')"; |
57 |
} |
58 |
|
59 |
// Set up colorScheme selector.
|
60 |
$('#edit-scheme', form).change(function () { |
61 |
var schemes = settings.color.schemes, colorScheme = this.options[this.selectedIndex].value; |
62 |
if (colorScheme != '' && schemes[colorScheme]) { |
63 |
// Get colors of active scheme.
|
64 |
colors = schemes[colorScheme]; |
65 |
for (field_name in colors) { |
66 |
callback($('#edit-palette-' + field_name), colors[field_name], false, true); |
67 |
} |
68 |
preview(); |
69 |
} |
70 |
}); |
71 |
|
72 |
/**
|
73 |
* Renders the preview.
|
74 |
*/
|
75 |
function preview() { |
76 |
Drupal.color.callback(context, settings, form, farb, height, width); |
77 |
} |
78 |
|
79 |
/**
|
80 |
* Shifts a given color, using a reference pair (ref in HSL).
|
81 |
*
|
82 |
* This algorithm ensures relative ordering on the saturation and luminance
|
83 |
* axes is preserved, and performs a simple hue shift.
|
84 |
*
|
85 |
* It is also symmetrical. If: shift_color(c, a, b) == d, then
|
86 |
* shift_color(d, b, a) == c.
|
87 |
*/
|
88 |
function shift_color(given, ref1, ref2) { |
89 |
// Convert to HSL.
|
90 |
given = farb.RGBToHSL(farb.unpack(given)); |
91 |
|
92 |
// Hue: apply delta.
|
93 |
given[0] += ref2[0] - ref1[0]; |
94 |
|
95 |
// Saturation: interpolate.
|
96 |
if (ref1[1] == 0 || ref2[1] == 0) { |
97 |
given[1] = ref2[1]; |
98 |
} |
99 |
else {
|
100 |
var d = ref1[1] / ref2[1]; |
101 |
if (d > 1) { |
102 |
given[1] /= d;
|
103 |
} |
104 |
else {
|
105 |
given[1] = 1 - (1 - given[1]) * d; |
106 |
} |
107 |
} |
108 |
|
109 |
// Luminance: interpolate.
|
110 |
if (ref1[2] == 0 || ref2[2] == 0) { |
111 |
given[2] = ref2[2]; |
112 |
} |
113 |
else {
|
114 |
var d = ref1[2] / ref2[2]; |
115 |
if (d > 1) { |
116 |
given[2] /= d;
|
117 |
} |
118 |
else {
|
119 |
given[2] = 1 - (1 - given[2]) * d; |
120 |
} |
121 |
} |
122 |
|
123 |
return farb.pack(farb.HSLToRGB(given));
|
124 |
} |
125 |
|
126 |
/**
|
127 |
* Callback for Farbtastic when a new color is chosen.
|
128 |
*/
|
129 |
function callback(input, color, propagate, colorScheme) { |
130 |
var matched;
|
131 |
// Set background/foreground colors.
|
132 |
$(input).css({
|
133 |
backgroundColor: color,
|
134 |
'color': farb.RGBToHSL(farb.unpack(color))[2] > 0.5 ? '#000' : '#fff' |
135 |
}); |
136 |
|
137 |
// Change input value.
|
138 |
if ($(input).val() && $(input).val() != color) { |
139 |
$(input).val(color);
|
140 |
|
141 |
// Update locked values.
|
142 |
if (propagate) {
|
143 |
i = input.i; |
144 |
for (j = i + 1; ; ++j) { |
145 |
if (!locks[j - 1] || $(locks[j - 1]).is('.unlocked')) break; |
146 |
matched = shift_color(color, reference[input.key], reference[inputs[j].key]); |
147 |
callback(inputs[j], matched, false);
|
148 |
} |
149 |
for (j = i - 1; ; --j) { |
150 |
if (!locks[j] || $(locks[j]).is('.unlocked')) break; |
151 |
matched = shift_color(color, reference[input.key], reference[inputs[j].key]); |
152 |
callback(inputs[j], matched, false);
|
153 |
} |
154 |
|
155 |
// Update preview.
|
156 |
preview(); |
157 |
} |
158 |
|
159 |
// Reset colorScheme selector.
|
160 |
if (!colorScheme) {
|
161 |
resetScheme(); |
162 |
} |
163 |
} |
164 |
} |
165 |
|
166 |
/**
|
167 |
* Resets the color scheme selector.
|
168 |
*/
|
169 |
function resetScheme() { |
170 |
$('#edit-scheme', form).each(function () { |
171 |
this.selectedIndex = this.options.length - 1; |
172 |
}); |
173 |
} |
174 |
|
175 |
/**
|
176 |
* Focuses Farbtastic on a particular field.
|
177 |
*/
|
178 |
function focus() { |
179 |
var input = this; |
180 |
// Remove old bindings.
|
181 |
focused && $(focused).unbind('keyup', farb.updateValue) |
182 |
.unbind('keyup', preview).unbind('keyup', resetScheme) |
183 |
.parent().removeClass('item-selected');
|
184 |
|
185 |
// Add new bindings.
|
186 |
focused = this;
|
187 |
farb.linkTo(function (color) { callback(input, color, true, false); }); |
188 |
farb.setColor(this.value);
|
189 |
$(focused).keyup(farb.updateValue).keyup(preview).keyup(resetScheme)
|
190 |
.parent().addClass('item-selected');
|
191 |
} |
192 |
|
193 |
// Initialize color fields.
|
194 |
$('#palette input.form-text', form) |
195 |
.each(function () {
|
196 |
// Extract palette field name
|
197 |
this.key = this.id.substring(13); |
198 |
|
199 |
// Link to color picker temporarily to initialize.
|
200 |
farb.linkTo(function () {}).setColor('#000').linkTo(this); |
201 |
|
202 |
// Add lock.
|
203 |
var i = inputs.length;
|
204 |
if (inputs.length) {
|
205 |
var lock = $('<div class="lock"></div>').toggle( |
206 |
function () {
|
207 |
$(this).addClass('unlocked'); |
208 |
$(hooks[i - 1]).attr('class', |
209 |
locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook up' : 'hook' |
210 |
); |
211 |
$(hooks[i]).attr('class', |
212 |
locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook down' : 'hook' |
213 |
); |
214 |
}, |
215 |
function () {
|
216 |
$(this).removeClass('unlocked'); |
217 |
$(hooks[i - 1]).attr('class', |
218 |
locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook both' : 'hook down' |
219 |
); |
220 |
$(hooks[i]).attr('class', |
221 |
locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook both' : 'hook up' |
222 |
); |
223 |
} |
224 |
); |
225 |
$(this).after(lock); |
226 |
locks.push(lock); |
227 |
}; |
228 |
|
229 |
// Add hook.
|
230 |
var hook = $('<div class="hook"></div>'); |
231 |
$(this).after(hook); |
232 |
hooks.push(hook); |
233 |
|
234 |
$(this).parent().find('.lock').click(); |
235 |
this.i = i;
|
236 |
inputs.push(this);
|
237 |
}) |
238 |
.focus(focus); |
239 |
|
240 |
$('#palette label', form); |
241 |
|
242 |
// Focus first color.
|
243 |
focus.call(inputs[0]);
|
244 |
|
245 |
// Render preview.
|
246 |
preview(); |
247 |
} |
248 |
}; |
249 |
|
250 |
})(jQuery); |