GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

third-party/PDF engine/dompdf/dompdf-0.6.2/www/cssSandpaper/js/cssSandpaper.js   F
last analyzed

Complexity

Total Complexity 349
Complexity/F 2.75

Size

Lines of Code 2371
Function Count 127

Duplication

Duplicated Lines 2371
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 1303
dl 2371
loc 2371
rs 0.8
c 0
b 0
f 0
wmc 349
mnd 222
bc 222
fnc 127
bpm 1.748
cpm 2.748
noi 75

27 Functions

Rating   Name   Duplication   Size   Complexity  
F cssSandpaper.js ➔ RGBColor 370 370 43
B cssSandpaper.js ➔ parseColorStop 32 32 6
B cssSandpaper.js ➔ indexRules 31 31 8
F cssSandpaper.js ➔ fixLinearGradients 12 12 22
F cssSandpaper.js ➔ swapIndices 5 5 43
A cssSandpaper.js ➔ setGradientFilter 19 19 2
C cssSandpaper.js ➔ fixOpacity 15 15 10
A cssSandpaper.js ➔ addIETransformWorkaround 95 95 3
A cssSandpaper.js ➔ normalizePercentage 8 8 2
A cssSandpaper.js ➔ getClassReString 3 3 5
A cssSandpaper.js ➔ setClasses 20 20 4
F cssSandpaper.js ➔ hasIETransformWorkaround 4 4 26
F cssSandpaper.js ➔ StringBuffer 28 28 16
A cssSandpaper.js ➔ degreesToRadians 3 3 4
A cssSandpaper.js ➔ RuleList 8 8 2
B cssSandpaper.js ➔ fixTransforms 17 17 6
A cssSandpaper.js ➔ getRuleList 7 7 2
A cssSandpaper.js ➔ getStyleSheet 18 18 2
A cssSandpaper.js ➔ getRadianScalar 32 32 4
B cssSandpaper.js ➔ MSFilter 52 52 7
B cssSandpaper.js ➔ fixBoxShadow 22 22 6
B cssSandpaper.js ➔ fixBackgrounds 23 23 6
A cssSandpaper.js ➔ getStyleSheets 10 10 3
A cssSandpaper.js ➔ CSSRule 10 10 2
F cssSandpaper.js ➔ MSFilterList 54 54 21
A cssSandpaper.js ➔ listColorStops 12 12 3
C cssSandpaper.js ➔ fixColors 41 41 11

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like third-party/PDF engine/dompdf/dompdf-0.6.2/www/cssSandpaper/js/cssSandpaper.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
2
/*******************************************************************************
3
 * This notice must be untouched at all times.
4
 *
5
 * CSS Sandpaper: smooths out differences between CSS implementations.
6
 *
7
 * This javascript library contains routines to implement the CSS transform,
8
 * box-shadow and gradient in IE.  It also provides a common syntax for other
9
 * browsers that support vendor-specific methods.
10
 *
11
 * Written by: Zoltan Hawryluk. Version 1.0 beta 1 completed on March 8, 2010.
12
 *
13
 * Some routines are based on code from CSS Gradients via Canvas v1.2
14
 * by Weston Ruter <http://weston.ruter.net/projects/css-gradients-via-canvas/>
15
 *
16
 * Requires sylvester.js by James Coglan http://sylvester.jcoglan.com/
17
 *
18
 * cssSandpaper.js v.1.0 beta 1 available at http://www.useragentman.com/
19
 *
20
 * released under the MIT License:
21
 *   http://www.opensource.org/licenses/mit-license.php
22
 *
23
 ******************************************************************************/
24 View Code Duplication
if (!document.querySelectorAll) {
25
    document.querySelectorAll = cssQuery;
26
}
27
28
var cssSandpaper = new function(){
29
    var me = this;
30
    
31
    var styleNodes, styleSheets = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
32
    
33
    var ruleSetRe = /[^\{]*{[^\}]*}/g;
34
    var ruleSplitRe = /[\{\}]/g;
35
    
36
    var reGradient = /gradient\([\s\S]*\)/g;
0 ignored issues
show
Unused Code introduced by
The variable reGradient seems to be never used. Consider removing it.
Loading history...
37
    var reHSL = /hsl\([\s\S]*\)/g;
38
    
39
    // This regexp from the article 
40
    // http://james.padolsey.com/javascript/javascript-comment-removal-revisted/
41
    var reMultiLineComment = /\/\/.+?(?=\n|\r|$)|\/\*[\s\S]+?\*\//g;
42
    
43
    var reAtRule = /@[^\{\};]*;|@[^\{\};]*\{[^\}]*\}/g;
44
    
45
    var reFunctionSpaces = /\(\s*/g
0 ignored issues
show
Unused Code introduced by
The variable reFunctionSpaces seems to be never used. Consider removing it.
Loading history...
46
    
47
    
48
    var ruleLists = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
49
    var styleNode;
0 ignored issues
show
Unused Code introduced by
The variable styleNode seems to be never used. Consider removing it.
Loading history...
50
    
51
    var tempObj;
52
    var body;
53
    
54
    
55
    me.init = function(reinit){
56
   
57
        if (EventHelpers.hasPageLoadHappened(arguments) && !reinit) {
58
            return;
59
        }
60
		
61
        body = document.body;
62
        
63
        tempObj = document.createElement('div');
0 ignored issues
show
Unused Code introduced by
The variable tempObj seems to be never used. Consider removing it.
Loading history...
64
        
65
        getStyleSheets();
66
        
67
        indexRules();
68
        
69
        
70
        fixTransforms();
71
        fixBoxShadow();
72
        fixLinearGradients();
73
        
74
        fixBackgrounds();
75
       	fixColors();
76
        fixOpacity();
77
        setClasses();
78
        //fixBorderRadius();
79
    
80
    }
81
    
82
    me.setOpacity = function(obj, value){
83
        var property = CSS3Helpers.findProperty(document.body, 'opacity');
84
        
85
        if (property == "filter") {
86
            // IE must have layout, see 
87
            // http://jszen.blogspot.com/2005/04/ie6-opacity-filter-caveat.html
88
            // for details.
89
            obj.style.zoom = "100%";
90
            
91
            var filter = CSS3Helpers.addFilter(obj, 'DXImageTransform.Microsoft.Alpha', StringHelpers.sprintf("opacity=%d", ((value) * 100)));
92
            
93
            filter.opacity = value * 100;
94
            
95
            
96
        } else if (obj.style[property] != null) {
97
            obj.style[property] = value;
98
        }
99
    }
100
    
101
    
102
    function fixOpacity(){
103
    
104
        var transformRules = getRuleList('opacity').values;
105
        
106
        for (var i in transformRules) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
107
            var rule = transformRules[i];
108
            var nodes = document.querySelectorAll(rule.selector);
109
            
110
            for (var j = 0; j < nodes.length; j++) {
111
                me.setOpacity(nodes[j], rule.value)
112
            }
113
            
114
        }
115
        
116
    }
117
    
118
    
119
    
120
    me.setTransform = function(obj, transformString){
121
        var property = CSS3Helpers.findProperty(obj, 'transform');
122
        
123
        if (property == "filter") {
124
            var matrix = CSS3Helpers.getTransformationMatrix(transformString);
125
            CSS3Helpers.setMatrixFilter(obj, matrix)
126
        } else if (obj.style[property] != null) {
127
            obj.style[property] = transformString;
128
        }
129
    }
130
    
131
    function fixTransforms(){
132
    
133
        var transformRules = getRuleList('-sand-transform').values;
134
        var property = CSS3Helpers.findProperty(document.body, 'transform');
0 ignored issues
show
Unused Code introduced by
The variable property seems to be never used. Consider removing it.
Loading history...
135
        
136
        
137
        for (var i in transformRules) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
138
            var rule = transformRules[i];
139
            var nodes = document.querySelectorAll(rule.selector);
140
            
141
            for (var j = 0; j < nodes.length; j++) {
142
                me.setTransform(nodes[j], rule.value)
143
            }
144
            
145
        }
146
        
147
    }
148
    
149
    me.setBoxShadow = function(obj, value){
150
        var property = CSS3Helpers.findProperty(obj, 'boxShadow');
151
        
152
        var values = CSS3Helpers.getBoxShadowValues(value);
153
        
154
        if (property == "filter") {
155
            var filter = CSS3Helpers.addFilter(obj, 'DXImageTransform.Microsoft.DropShadow', StringHelpers.sprintf("color=%s,offX=%d,offY=%d", values.color, values.offsetX, values.offsetY));
156
            filter.color = values.color;
157
            filter.offX = values.offsetX;
158
            filter.offY = values.offsetY;
159
            
160
        } else if (obj.style[property] != null) {
161
            obj.style[property] = value;
162
        }
163
    }
164
    
165
    function fixBoxShadow(){
166
    
167
        var transformRules = getRuleList('-sand-box-shadow').values;
168
        
169
        //var matrices = new Array();
170
        
171
        
172
        for (var i in transformRules) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
173
            var rule = transformRules[i];
174
            
175
            var nodes = document.querySelectorAll(rule.selector);
176
            
177
            
178
            
179
            for (var j = 0; j < nodes.length; j++) {
180
                me.setBoxShadow(nodes[j], rule.value)
181
                
182
            }
183
            
184
        }
185
        
186
    }
187
    
188
    function setGradientFilter(node, values){
189
    
190
        if (values.colorStops.length == 2 &&
191
        values.colorStops[0].stop == 0.0 &&
192
        values.colorStops[1].stop == 1.0) {
193
            var startColor = new RGBColor(values.colorStops[0].color);
194
            var endColor = new RGBColor(values.colorStops[1].color);
195
            
196
            startColor = startColor.toHex();
197
            endColor = endColor.toHex();
198
            
199
            var filter = CSS3Helpers.addFilter(node, 'DXImageTransform.Microsoft.Gradient', StringHelpers.sprintf("GradientType = %s, StartColorStr = '%s', EndColorStr = '%s'", values.IEdir, startColor, endColor));
200
            
201
            filter.GradientType = values.IEdir;
202
            filter.StartColorStr = startColor;
203
            filter.EndColorStr = endColor;
204
            node.style.zoom = 1;
205
        }
206
    }
207
    
208
    me.setGradient = function(node, value){
209
    
210
        var support = CSS3Helpers.reportGradientSupport();
211
        
212
        var values = CSS3Helpers.getGradient(value);
213
        
214
        if (values == null) {
215
            return;
216
        }
217
        
218
        if (node.filters) {
219
            setGradientFilter(node, values);
220
        } else if (support == implementation.MOZILLA) {
221
        	
222
            node.style.backgroundImage = StringHelpers.sprintf('-moz-gradient( %s, %s, from(%s), to(%s))', values.dirBegin, values.dirEnd, values.colorStops[0].color, values.colorStops[1].color);
223
        } else if (support == implementation.WEBKIT) {
224
            var tmp = StringHelpers.sprintf('-webkit-gradient(%s, %s, %s %s, %s %s)', values.type, values.dirBegin, values.r0 ? values.r0 + ", " : "", values.dirEnd, values.r1 ? values.r1 + ", " : "", listColorStops(values.colorStops));
225
            node.style.backgroundImage = tmp;
226
        } else if (support == implementation.CANVAS_WORKAROUND) {
227
            try {
228
                CSS3Helpers.applyCanvasGradient(node, values);
229
            } 
230
            catch (ex) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
231
                // do nothing (for now).
232
            }
233
        }
234
    }
235
    
236
    me.setRGBABackground = function(node, value){
237
    
238
        var support = CSS3Helpers.reportColorSpaceSupport('RGBA', colorType.BACKGROUND);
239
        
240
        switch (support) {
241
            case implementation.NATIVE:
242
                node.style.value = value;
243
                break;
244
            case implementation.FILTER_WORKAROUND:
245
                setGradientFilter(node, {
246
                    IEdir: 0,
247
                    colorStops: [{
248
                        stop: 0.0,
249
                        color: value
250
                    }, {
251
                        stop: 1.0,
252
                        color: value
253
                    }]
254
                });
255
                
256
                break;
257
        }
258
        
259
    }
260
    
261
    me.setHSLABackground = function(node, value) {
262
    	var support = CSS3Helpers.reportColorSpaceSupport('HSLA', colorType.BACKGROUND);
263
        
264
        switch (support) {
265
            case implementation.NATIVE:
266
                /* node.style.value = value;
267
                break; */
268
            case implementation.FILTER_WORKAROUND:
269
            	var rgbColor =  new RGBColor(value);
270
            	
271
            	if (rgbColor.a == 1) {
272
            		node.style.backgroundColor = rgbColor.toHex();
273
            	} else {
274
            		var rgba = rgbColor.toRGBA();
275
	                setGradientFilter(node, {
276
	                    IEdir: 0,
277
	                    colorStops: [{
278
	                        stop: 0.0,
279
	                        color: rgba
280
	                    }, {
281
	                        stop: 1.0,
282
	                        color: rgba
283
	                    }]
284
	                });
285
                }
286
                break;
287
        }
288
    }
289
    
290
    /**
291
	 * Convert a hyphenated string to camelized text.  For example, the string "font-type" will be converted
292
	 * to "fontType".
293
	 * 
294
	 * @param {Object} s - the string that needs to be camelized.
295
	 * @return {String} - the camelized text.
296
	 */
297
	me.camelize = function (s) {
298
		var r="";
299
		
300
		for (var i=0; i<s.length; i++) {
301
			if (s.substring(i, i+1) == '-') {
302
				i++;
0 ignored issues
show
Complexity Coding Style introduced by
You seem to be assigning a new value to the loop variable i here. Please check if this was indeed your intention. Even if it was, consider using another kind of loop instead.
Loading history...
303
				r+= s.substring(i, i+1).toUpperCase();
304
			} else {
305
				r+= s.substring(i, i+1);
306
			}
307
		}
308
		
309
		return r;
310
	}
311
    
312
    me.setHSLColor = function (node, property, value) {
313
    	var support = CSS3Helpers.reportColorSpaceSupport('HSL', colorType.FOREGROUND);
314
    	
315
    	switch (support) {
316
            case implementation.NATIVE:
317
                /* node.style.value = value;
318
                break; */
319
            case implementation.HEX_WORKAROUND:
320
            	
321
            	var hslColor = value.match(reHSL)[0];
322
            	var hexColor = new RGBColor(hslColor).toHex()
323
            	var newPropertyValue = value.replace(reHSL, hexColor);
324
            	
325
            	
326
            	
327
                node.style[me.camelize(property)] = newPropertyValue;
328
                
329
                break;
330
        }
331
    		
332
    }
333
    
334
    
335
    function fixLinearGradients(){
336
    
337
        var backgroundRules = getRuleList('background').values.concat(getRuleList('background-image').values);
338
        
339
        for (var i in backgroundRules) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
340
            var rule = backgroundRules[i];
341
            var nodes = document.querySelectorAll(rule.selector);
342
            for (var j = 0; j < nodes.length; j++) {
343
                me.setGradient(nodes[j], rule.value)
344
            }
345
        }
346
    }
347
    
348
    function fixBackgrounds(){
349
    
350
        var support = CSS3Helpers.reportColorSpaceSupport('RGBA', colorType.BACKGROUND);
351
        if (support == implementation.NATIVE) {
352
            return;
353
        } 
354
       
355
        
356
        var backgroundRules = getRuleList('background').values.concat(getRuleList('background-color').values);
357
       
358
        for (var i in backgroundRules) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
359
            var rule = backgroundRules[i];
360
            var nodes = document.querySelectorAll(rule.selector);
361
            for (var j = 0; j < nodes.length; j++) {
362
                if (rule.value.indexOf('rgba(') == 0) {
363
                    me.setRGBABackground(nodes[j], rule.value);
364
                } else if (rule.value.indexOf('hsla(') == 0 || rule.value.indexOf('hsl(') == 0) {
365
                	
366
                	me.setHSLABackground(nodes[j], rule.value);
367
                } 
368
            }
369
        }
370
    }
371
    
372
    me.getProperties = function (obj, objName)
373
	{
374
		var result = ""
375
		
376
		if (!obj) {
377
			return result;
378
		}
379
		
380
		for (var i in obj)
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
381
		{
382
			try {
383
				result += objName + "." + i.toString() + " = " + obj[i] + ", ";
384
			} catch (ex) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
385
				// nothing
386
			}
387
		}
388
		return result
389
	}
390
    
391
    function fixColors() {
392
    	var support = CSS3Helpers.reportColorSpaceSupport('HSL', colorType.FOREGROUND);
393
    	if (support == implementation.NATIVE) {
394
            return;
395
        } 
396
        
397
        var colorRules = getRuleList('color').values;
398
        
399
        var properties = ['color', 'border', 
400
        	'border-left', 	'border-right', 'border-bottom', 'border-top',
401
        	'border-left-color', 'border-right-color', 'border-bottom-color', 'border-top-color'];
402
        
403
        for (var i=0; i<properties.length; i++) {
404
        	var rules = getRuleList(properties[i]).values;
405
    		colorRules = colorRules.concat(rules);
406
       	} 
407
       	
408
        for (var i in colorRules) {
0 ignored issues
show
Complexity Coding Style introduced by
You seem to be assigning a new value to the loop variable i here. Please check if this was indeed your intention. Even if it was, consider using another kind of loop instead.
Loading history...
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
Comprehensibility Naming Best Practice introduced by
The variable i already seems to be declared on line 403. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
409
            var rule = colorRules[i];
410
            
411
            var nodes = document.querySelectorAll(rule.selector);
412
            for (var j = 0; j < nodes.length; j++) {
413
            	var isBorder = (rule.name.indexOf('border') == 0);
414
            	var ruleMatch = rule.value.match(reHSL);
415
            	
416
            	
417
                if (ruleMatch) {
418
                	
419
                	var cssProperty;
420
                	if (isBorder && rule.name.indexOf('-color') < 0) {
421
                		cssProperty = rule.name;
422
                	} else {
423
                		cssProperty = rule.name;
424
                	}
425
                	
426
                	me.setHSLColor(nodes[j], cssProperty, rule.value);
427
                			
428
                } 
429
            }
430
        }
431
    }
432
    
433
    
434
    
435
    function listColorStops(colorStops){
436
        var sb = new StringBuffer();
437
        
438
        for (var i = 0; i < colorStops.length; i++) {
439
            sb.append(StringHelpers.sprintf("color-stop(%s, %s)", colorStops[i].stop, colorStops[i].color));
440
            if (i < colorStops.length - 1) {
441
                sb.append(', ');
442
            }
443
        }
444
        
445
        return sb.toString();
446
    }
447
    
448
    
449
    function getStyleSheet(node){
450
        var sheetCssText;
451
        switch (node.nodeName.toLowerCase()) {
452
            case 'style':
453
                sheetCssText = StringHelpers.uncommentHTML(node.innerHTML); //does not work with inline styles because IE doesn't allow you to get the text content of a STYLE element
454
                break;
455
            case 'link':
456
                
457
                var xhr = XMLHelpers.getXMLHttpRequest(node.href, null, "GET", null, false);
458
                sheetCssText = xhr.responseText;
459
                
460
                break;
461
        }
462
        
463
        sheetCssText = sheetCssText.replace(reMultiLineComment, '').replace(reAtRule, '');
464
        
465
        return sheetCssText;
466
    }
467
    
468
    function getStyleSheets(){
469
    
470
        styleNodes = document.querySelectorAll('style, link[rel="stylesheet"]');
471
        
472
        for (var i = 0; i < styleNodes.length; i++) {
473
            if (!CSSHelpers.isMemberOfClass(styleNodes[i], 'cssSandpaper-noIndex')) {
474
                styleSheets.push(getStyleSheet(styleNodes[i]))
475
            }
476
        }
477
    }
478
    
479
    function indexRules(){
480
    
481
        for (var i = 0; i < styleSheets.length; i++) {
482
            var sheet = styleSheets[i];
483
            
484
            rules = sheet.match(ruleSetRe);
0 ignored issues
show
Bug introduced by
The variable rules seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rules.
Loading history...
485
            if (rules) {
486
                for (var j = 0; j < rules.length; j++) {
487
                    var parsedRule = rules[j].split(ruleSplitRe);
488
                    var selector = parsedRule[0].trim();
489
                    var propertiesStr = parsedRule[1];
490
                    var properties = propertiesStr.split(';');
491
                    for (var k = 0; k < properties.length; k++) {
492
                        if (properties[k].trim() != '') {
493
                            var splitProperty = properties[k].split(':')
494
                            var name = splitProperty[0].trim().toLowerCase();
495
                            var value = splitProperty[1];
496
                            if (!ruleLists[name]) {
497
                                ruleLists[name] = new RuleList(name);
498
                            }
499
                            
500
                            if (value && typeof(ruleLists[name]) == 'object') {
501
                                ruleLists[name].add(selector, value.trim());
502
                            }
503
                        }
504
                    }
505
                }
506
            }
507
        }
508
        
509
    }
510
    
511
    function getRuleList(name){
512
        var list = ruleLists[name];
513
        if (!list) {
514
            list = new RuleList(name);
515
        }
516
        return list;
517
    }
518
    
519
    function setClasses(){
520
    
521
    
522
        var htmlNode = document.getElementsByTagName('html')[0];
523
        var properties = ['transform', 'opacity'];
524
        
525
        for (var i = 0; i < properties.length; i++) {
526
            var prop = properties[i];
527
            if (CSS3Helpers.supports(prop)) {
528
                CSSHelpers.addClass(htmlNode, 'cssSandpaper-' + prop);
529
            }
530
        }
531
		
532
		// Now .. remove the initially hidden classes
533
		var hiddenNodes = CSSHelpers.getElementsByClassName(document, 'cssSandpaper-initiallyHidden');
534
		
535
		for (var i=0; i<hiddenNodes.length; i++){
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i already seems to be declared on line 525. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
536
			CSSHelpers.removeClass(hiddenNodes[i], 'cssSandpaper-initiallyHidden');
537
		} 
538
    }
539
}
540
541
function RuleList(propertyName){
542
    var me = this;
543
    me.values = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
544
    me.propertyName = propertyName;
545
    me.add = function(selector, value){
546
        me.values.push(new CSSRule(selector, me.propertyName, value));
547
    }
548
}
549
550
function CSSRule(selector, name, value){
551
    var me = this;
552
    me.selector = selector;
553
    me.name = name;
554
    me.value = value;
555
    
556
    me.toString = function(){
557
        return StringHelpers.sprintf("%s { %s: %s}", me.selector, me.name, me.value);
558
    }
559
}
560
561
var MatrixGenerator = new function(){
562
    var me = this;
563
    var reUnit = /[a-z]+$/;
564
    me.identity = $M([[1, 0, 0], [0, 1, 0], [0, 0, 1]]);
565
    
566
    
567
    function degreesToRadians(degrees){
568
        return (degrees - 360) * Math.PI / 180;
569
    }
570
    
571
    function getRadianScalar(angleStr){
572
    
573
        var num = parseFloat(angleStr);
574
        var unit = angleStr.match(reUnit);
575
		
576
		
577
		if (angleStr.trim() == '0') {
578
			num = 0;
579
			unit = 'rad';
580
		}
581
        
582
        if (unit.length != 1 || num == 0) {
583
            return 0;
584
        }
585
        
586
        
587
        unit = unit[0];
588
        
589
        
590
        var rad;
591
        switch (unit) {
592
            case "deg":
593
                rad = degreesToRadians(num);
594
                break;
595
            case "rad":
596
                rad = num;
597
                break;
598
            default:
599
                throw "Not an angle: " + angleStr;
600
        }
601
        return rad;
602
    }
603
    
604
    me.prettyPrint = function(m){
605
        return StringHelpers.sprintf('| %s %s %s | - | %s %s %s | - |%s %s %s|', m.e(1, 1), m.e(1, 2), m.e(1, 3), m.e(2, 1), m.e(2, 2), m.e(2, 3), m.e(3, 1), m.e(3, 2), m.e(3, 3))
606
    }
607
    
608
    me.rotate = function(angleStr){
609
        var num = getRadianScalar(angleStr);
610
        return Matrix.RotationZ(num);
611
    }
612
    
613
    me.scale = function(sx, sy){
614
        sx = parseFloat(sx)
615
        
616
        if (!sy) {
617
            sy = sx;
618
        } else {
619
            sy = parseFloat(sy)
620
        }
621
        
622
        
623
        return $M([[sx, 0, 0], [0, sy, 0], [0, 0, 1]]);
624
    }
625
    
626
    me.scaleX = function(sx){
627
        return me.scale(sx, 1);
628
    }
629
    
630
    me.scaleY = function(sy){
631
        return me.scale(1, sy);
632
    }
633
    
634
    me.skew = function(ax, ay){
635
        var xRad = getRadianScalar(ax);
636
        var yRad;
637
        
638
        if (ay != null) {
639
            yRad = getRadianScalar(ay)
640
        } else {
641
            yRad = xRad
642
        }
643
		
644
		if (xRad != null && yRad != null) {
645
			
646
			return $M([[1, Math.tan(xRad), 0], [Math.tan(yRad), 1, 0], [0, 0, 1]]);
647
		} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
648
			return null;
649
		}
650
    }
651
    
652
    me.skewX = function(ax){
653
    
654
        return me.skew(ax, "0");
655
    }
656
    
657
    me.skewY = function(ay){
658
        return me.skew("0", ay);
659
    }
660
    
661
    me.translate = function(tx, ty){
662
    
663
        var TX = parseInt(tx);
664
        var TY = parseInt(ty)
665
        
666
        //jslog.debug(StringHelpers.sprintf('translate %f %f', TX, TY));
667
        
668
        return $M([[1, 0, TX], [0, 1, TY], [0, 0, 1]]);
669
    }
670
    
671
    me.translateX = function(tx){
672
        return me.translate(tx, 0);
673
    }
674
    
675
    me.translateY = function(ty){
676
        return me.translate(0, ty);
677
    }
678
    
679
    
680
    me.matrix = function(a, b, c, d, e, f){
681
    
682
        // for now, e and f are ignored
683
        return $M([[a, c, parseInt(e)], [b, d, parseInt(f)], [0, 0, 1]])
684
    }
685
}
686
687
var CSS3Helpers = new function(){
688
    var me = this;
689
    
690
    
691
    var reTransformListSplitter = /[a-zA-Z]+\([^\)]*\)\s*/g;
692
    
693
    var reLeftBracket = /\(/g;
694
    var reRightBracket = /\)/g;
695
    var reComma = /,/g;
696
    
697
    var reSpaces = /\s+/g
698
    
699
    var reFilterNameSplitter = /progid:([^\(]*)/g;
0 ignored issues
show
Unused Code introduced by
The variable reFilterNameSplitter seems to be never used. Consider removing it.
Loading history...
700
    
701
    var reLinearGradient
0 ignored issues
show
Unused Code introduced by
The variable reLinearGradient seems to be never used. Consider removing it.
Loading history...
702
    
703
    var canvas;
704
    
705
    var cache = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
706
    
707
    
708
    me.supports = function(cssProperty){
709
        if (CSS3Helpers.findProperty(document.body, cssProperty) != null) {
710
            return true;
711
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
712
            return false;
713
        }
714
    }
715
    
716
    me.getCanvas = function(){
717
    
718
        if (canvas) {
719
            return canvas;
720
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
721
            canvas = document.createElement('canvas');
722
            return canvas;
723
        }
724
    }
725
    
726
    me.getTransformationMatrix = function(CSS3TransformProperty, doThrowIfError){
727
    
728
        var transforms = CSS3TransformProperty.match(reTransformListSplitter);
729
		
730
		/*
731
		 * Do a check here to see if there is anything in the transformation
732
		 * besides legit transforms
733
		 */
734
		if (doThrowIfError) {
735
			var checkString = transforms.join(" ").replace(/\s*/g, ' ');
736
			var normalizedCSSProp = CSS3TransformProperty.replace(/\s*/g, ' ');
737
			
738
			if (checkString != normalizedCSSProp) {
739
				throw ("An invalid transform was given.")	
740
			}
741
		}
742
		
743
		
744
        var resultantMatrix = MatrixGenerator.identity;
745
        
746
        for (var j = 0; j < transforms.length; j++) {
747
        
748
            var transform = transforms[j];
749
			
750
            transform = transform.replace(reLeftBracket, '("').replace(reComma, '", "').replace(reRightBracket, '")');
751
            
752
            
753
            try {
754
                var matrix = eval('MatrixGenerator.' + transform);
0 ignored issues
show
Security Performance introduced by
Calls to eval are slow and potentially dangerous, especially on untrusted code. Please consider whether there is another way to achieve your goal.
Loading history...
755
				
756
				
757
                //jslog.debug( transform + ': ' + MatrixGenerator.prettyPrint(matrix))
758
                resultantMatrix = resultantMatrix.x(matrix);
759
            } 
760
            catch (ex) {
761
            	
762
				if (doThrowIfError) {
763
					var method = transform.split('(')[0];
764
765
					var funcCall = transform.replace(/\"/g, '');
766
767
					if (MatrixGenerator[method]  == undefined) {
768
						throw "Error: invalid tranform function: " + funcCall;
769
					} else {
770
						throw "Error: Invalid or missing parameters in function call: " + funcCall;
771
772
					}
773
				}
774
                // do nothing;
775
            }
776
        }
777
        
778
        return resultantMatrix;
779
        
780
    }
781
    
782
    me.getBoxShadowValues = function(propertyValue){
783
        var r = new Object();
784
        
785
        var values = propertyValue.split(reSpaces);
786
        
787
        if (values[0] == 'inset') {
788
            r.inset = true;
789
            values = values.reverse().pop().reverse();
790
        } else {
791
            r.inset = false;
792
        }
793
        
794
        r.offsetX = parseInt(values[0]);
795
        r.offsetY = parseInt(values[1]);
796
        
797
        if (values.length > 3) {
798
            r.blurRadius = values[2];
799
            
800
            if (values.length > 4) {
801
                r.spreadRadius = values[3]
802
            }
803
        }
804
        
805
        r.color = values[values.length - 1];
806
        
807
        return r;
808
    }
809
    
810
    me.getGradient = function(propertyValue){
811
        var r = new Object();
812
        r.colorStops = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
813
        
814
        
815
        var substring = me.getBracketedSubstring(propertyValue, '-sand-gradient');
816
        if (substring == undefined) {
817
            return null;
818
        }
819
        var parameters = substring.match(/[^\(,]+(\([^\)]*\))?[^,]*/g); //substring.split(reComma);
820
        r.type = parameters[0].trim();
821
        
822
        if (r.type == 'linear') {
823
            r.dirBegin = parameters[1].trim();
824
            r.dirEnd = parameters[2].trim();
825
            var beginCoord = r.dirBegin.split(reSpaces);
826
            var endCoord = r.dirEnd.split(reSpaces);
827
            
828
            for (var i = 3; i < parameters.length; i++) {
829
                r.colorStops.push(parseColorStop(parameters[i].trim(), i - 3));
830
            }
831
            
832
            
833
            
834
            
835
            /* The following logic only applies to IE */
836
            if (document.body.filters) {
837
                if (r.x0 == r.x1) {
838
                    /* IE only supports "center top", "center bottom", "top left" and "top right" */
839
                    
840
                    switch (beginCoord[1]) {
841
                        case 'top':
842
                            r.IEdir = 0;
843
                            break;
844
                        case 'bottom':
845
                            swapIndices(r.colorStops, 0, 1);
846
                            r.IEdir = 0;
847
                            /* r.from = parameters[4].trim();
848
                         r.to = parameters[3].trim(); */
849
                            break;
850
                    }
851
                }
852
                
853
                if (r.y0 == r.y1) {
854
                    switch (beginCoord[0]) {
855
                        case 'left':
856
                            r.IEdir = 1;
857
                            break;
858
                        case 'right':
859
                            r.IEdir = 1;
860
                            swapIndices(r.colorStops, 0, 1);
861
                            
862
                            break;
863
                    }
864
                }
865
            }
866
        } else {
867
        
868
            // don't even bother with IE
869
            if (document.body.filters) {
870
                return null;
871
            }
872
            
873
            
874
            r.dirBegin = parameters[1].trim();
875
            r.r0 = parameters[2].trim();
876
            
877
            r.dirEnd = parameters[3].trim();
878
            r.r1 = parameters[4].trim();
879
            
880
            var beginCoord = r.dirBegin.split(reSpaces);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable beginCoord already seems to be declared on line 825. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
881
            var endCoord = r.dirEnd.split(reSpaces);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable endCoord already seems to be declared on line 826. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
882
            
883
            for (var i = 5; i < parameters.length; i++) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i already seems to be declared on line 828. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
884
                r.colorStops.push(parseColorStop(parameters[i].trim(), i - 5));
885
            }
886
            
887
        }
888
        
889
        
890
        r.x0 = beginCoord[0];
891
        r.y0 = beginCoord[1];
892
        
893
        r.x1 = endCoord[0];
894
        r.y1 = endCoord[1];
895
        
896
        return r;
897
    }
898
    
899
    function swapIndices(array, index1, index2){
900
        var tmp = array[index1];
901
        array[index1] = array[index2];
902
        array[index2] = tmp;
903
    }
904
    
905
    function parseColorStop(colorStop, index){
906
        var r = new Object();
907
        var substring = me.getBracketedSubstring(colorStop, 'color-stop');
908
        var from = me.getBracketedSubstring(colorStop, 'from');
909
        var to = me.getBracketedSubstring(colorStop, 'to');
910
        
911
        
912
        if (substring) {
913
            //color-stop
914
            var parameters = substring.split(',')
915
            r.stop = normalizePercentage(parameters[0].trim());
916
            r.color = parameters[1].trim();
917
        } else if (from) {
918
            r.stop = 0.0;
919
            r.color = from.trim();
920
        } else if (to) {
921
            r.stop = 1.0;
922
            r.color = to.trim();
923
        } else {
924
            if (index <= 1) {
925
                r.color = colorStop;
926
                if (index == 0) {
927
                    r.stop = 0.0;
928
                } else {
929
                    r.stop = 1.0;
930
                }
931
            } else {
932
                throw (StringHelpers.sprintf('invalid argument "%s"', colorStop));
933
            }
934
        }
935
        return r;
936
    }
937
    
938
    function normalizePercentage(s){
939
        if (s.substring(s.length - 1, s.length) == '%') {
940
            return parseFloat(s) / 100 + "";
941
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
942
            return s;
943
        }
944
        
945
    }
946
    
947
    me.reportGradientSupport = function(){
948
    
949
        if (!cache["gradientSupport"]) {
950
            var r;
951
            var div = document.createElement('div');
952
            div.style.cssText = "background-image:-webkit-gradient(linear, 0% 0%, 0% 100%, from(red), to(blue));";
953
            
954
            if (div.style.backgroundImage) {
955
                r = implementation.WEBKIT;
956
                
957
            } else {
958
            
959
                /* div.style.cssText = "background-image:-moz-linear-gradient(top, blue, white 80%, orange);";
960
                 
961
                 if (div.style.backgroundImage) {
962
                 
963
                 r = implementation.MOZILLA;
964
                 
965
                 } else { */
966
                var canvas = CSS3Helpers.getCanvas();
967
                if (canvas.getContext && canvas.toDataURL) {
968
                    r = implementation.CANVAS_WORKAROUND;
969
                    
970
                } else {
971
                    r = implementation.NONE;
972
                }
973
                /* } */
974
            }
975
            
976
            cache["gradientSupport"] = r;
977
        }
978
        return cache["gradientSupport"];
979
    }
980
    
981
    me.reportColorSpaceSupport = function(colorSpace, type){
982
    	
983
        if (!cache[colorSpace + type]) {
984
            var r;
985
            var div = document.createElement('div');
986
            
987
            switch (type) {
988
            	
989
            	case colorType.BACKGROUND:
990
            		
991
		            switch(colorSpace) {
992
		            	case 'RGBA':
993
		            		div.style.cssText = "background-color: rgba(255, 32, 34, 0.5)";
994
		            		break;
995
		            	case 'HSL': 
996
		            		div.style.cssText = "background-color: hsl(0,0%,100%)";
997
		            		break;
998
		            	case 'HSLA': 
999
		            		div.style.cssText = "background-color: hsla(0,0%,100%,.5)";
1000
		            		break;
1001
		            	
1002
		            	default:
1003
		            		break;
1004
		            }
1005
	            
1006
	            
1007
	            
1008
		            var body = document.body;
1009
		            
1010
		            
1011
		            if (div.style.backgroundColor) {
1012
		                r = implementation.NATIVE;
1013
		                
1014
		            } else if (body.filters && body.filters != undefined) {
1015
		                r = implementation.FILTER_WORKAROUND;
1016
		            } else {
1017
		                r = implementation.NONE;
1018
		            }
1019
		            break;
1020
		        case colorType.FOREGROUND:
1021
		        	switch(colorSpace) {
1022
		            	case 'RGBA':
1023
		            		div.style.cssText = "color: rgba(255, 32, 34, 0.5)";
1024
		            		break;
1025
		            	case 'HSL': 
1026
		            		div.style.cssText = "color: hsl(0,0%,100%)";
1027
		            		break;
1028
		            	case 'HSLA': 
1029
		            		div.style.cssText = "color: hsla(0,0%,100%,.5)";
1030
		            		break;
1031
		            	
1032
		            	default:
1033
		            		break;
1034
		            }
1035
		           
1036
		            if (div.style.color) {
1037
		                r = implementation.NATIVE; 
1038
		            } else if (colorSpace == 'HSL') {
1039
		            
1040
						r = implementation.HEX_WORKAROUND;
1041
		            } else {
1042
		                r = implementation.NONE;
1043
		            }
1044
		            break
1045
	        }
1046
           
1047
            
1048
            cache[colorSpace] = r;
1049
        }
1050
        return cache[colorSpace];
1051
    }
1052
    
1053
    
1054
    
1055
    me.getBracketedSubstring = function(s, header){
1056
        var gradientIndex = s.indexOf(header + '(')
1057
        
1058
        if (gradientIndex != -1) {
1059
            var substring = s.substring(gradientIndex);
1060
            
1061
            var openBrackets = 1;
1062
            for (var i = header.length + 1; i < 100 || i < substring.length; i++) {
1063
                var c = substring.substring(i, i + 1);
1064
                switch (c) {
1065
                    case "(":
1066
                        openBrackets++;
1067
                        break;
1068
                    case ")":
1069
                        openBrackets--;
1070
                        break;
1071
                }
1072
                
1073
                if (openBrackets == 0) {
1074
                    break;
1075
                }
1076
                
1077
            }
1078
            
1079
            return substring.substring(gradientIndex + header.length + 1, i);
1080
        }
1081
        
1082
        
1083
    }
1084
    
1085
    
1086
    me.setMatrixFilter = function(obj, matrix){
1087
	
1088
	
1089
		if (!hasIETransformWorkaround(obj)) {
1090
			addIETransformWorkaround(obj)
1091
		}
1092
		
1093
		var container = obj.parentNode;
1094
		//container.xTransform = degrees;
1095
		
1096
		
1097
		filter = obj.filters.item('DXImageTransform.Microsoft.Matrix');
0 ignored issues
show
Bug introduced by
The variable filter seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.filter.
Loading history...
1098
		//jslog.debug(MatrixGenerator.prettyPrint(matrix))
1099
		filter.M11 = matrix.e(1, 1);
1100
		filter.M12 = matrix.e(1, 2);
1101
		filter.M21 = matrix.e(2, 1);
1102
		filter.M22 = matrix.e(2, 2);
1103
		
1104
		
1105
		// Now, adjust the margins of the parent object
1106
		var offsets = me.getIEMatrixOffsets(obj, matrix, container.xOriginalWidth, container.xOriginalHeight);
1107
		container.style.marginLeft = offsets.x;
1108
		container.style.marginTop = offsets.y;
1109
		container.style.marginRight = 0;
1110
		container.style.marginBottom = 0;
1111
	}
1112
	
1113
	me.getTransformedDimensions = function (obj, matrix) {
1114
		var r = {};
1115
		
1116
		if (hasIETransformWorkaround(obj)) {
1117
			r.width = obj.offsetWidth;
1118
			r.height = obj.offsetHeight;
1119
		} else {
1120
			var pts = [
1121
				matrix.x($V([0, 0, 1]))	,
1122
				matrix.x($V([0, obj.offsetHeight, 1])),
1123
				matrix.x($V([obj.offsetWidth, 0, 1])),
1124
				matrix.x($V([obj.offsetWidth, obj.offsetHeight, 1]))
1125
			];
1126
			var maxX = 0, maxY =0, minX=0, minY=0;
1127
			
1128
			for (var i = 0; i < pts.length; i++) {
1129
				var pt = pts[i];
1130
				var x = pt.e(1), y = pt.e(2);
1131
				var minX = Math.min(minX, x);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable minX already seems to be declared on line 1126. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
1132
				var maxX = Math.max(maxX, x);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable maxX already seems to be declared on line 1126. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
1133
				var minY = Math.min(minY, y);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable minY already seems to be declared on line 1126. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
1134
				var maxY = Math.max(maxY, y);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable maxY already seems to be declared on line 1126. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
1135
			}
1136
			
1137
			
1138
				r.width = maxX - minX;
1139
				r.height = maxY - minY;
1140
				 
1141
		}
1142
		
1143
		return r;
1144
	}
1145
	
1146
	me.getIEMatrixOffsets = function (obj, matrix, width, height) {
1147
        var r = {};
1148
		
1149
		var originalWidth = parseFloat(width);
1150
		var originalHeight = parseFloat(height);
1151
		
1152
		
1153
        var offset;
1154
        if (CSSHelpers.getComputedStyle(obj, 'display') == 'inline') {
1155
            offset = 0;
1156
        } else {
1157
            offset = 13; // This works ... don't know why.
1158
        }
1159
		var transformedDimensions = me.getTransformedDimensions(obj, matrix);
1160
        
1161
        r.x = (((originalWidth - transformedDimensions.width) / 2) - offset + matrix.e(1, 3)) + 'px';
1162
        r.y  = (((originalHeight - transformedDimensions.height) / 2) - offset + matrix.e(2, 3)) + 'px';
1163
        
1164
		return r;
1165
    }
1166
    
1167
    function hasIETransformWorkaround(obj){
1168
    
1169
        return CSSHelpers.isMemberOfClass(obj.parentNode, 'IETransformContainer');
1170
    }
1171
    
1172
    function addIETransformWorkaround(obj){
1173
        if (!hasIETransformWorkaround(obj)) {
1174
            var parentNode = obj.parentNode;
1175
            var filter;
1176
            
1177
            // This is the container to offset the strange rotation behavior
1178
            var container = document.createElement('div');
1179
            CSSHelpers.addClass(container, 'IETransformContainer');
1180
            
1181
            
1182
            container.style.width = obj.offsetWidth + 'px';
1183
            container.style.height = obj.offsetHeight + 'px';
1184
            
1185
            container.xOriginalWidth = obj.offsetWidth;
1186
            container.xOriginalHeight = obj.offsetHeight;
1187
            container.style.position = 'absolute'
1188
            container.style.zIndex = obj.currentStyle.zIndex;
1189
            
1190
            
1191
            var horizPaddingFactor = 0; //parseInt(obj.currentStyle.paddingLeft); 
1192
            var vertPaddingFactor = 0; //parseInt(obj.currentStyle.paddingTop);
1193
            if (obj.currentStyle.display == 'block') {
1194
                container.style.left = obj.offsetLeft + 13 - horizPaddingFactor + "px";
1195
                container.style.top = obj.offsetTop + 13 + -vertPaddingFactor + 'px';
1196
            } else {
1197
                container.style.left = obj.offsetLeft + "px";
1198
                container.style.top = obj.offsetTop + 'px';
1199
                
1200
            }
1201
            //container.style.float = obj.currentStyle.float;
1202
            
1203
            
1204
            obj.style.top = "auto";
1205
            obj.style.left = "auto"
1206
            obj.style.bottom = "auto";
1207
            obj.style.right = "auto";
1208
            // This is what we need in order to insert to keep the document
1209
            // flow ok
1210
            var replacement = obj.cloneNode(true);
1211
            replacement.style.visibility = 'hidden';
1212
            
1213
            obj.replaceNode(replacement);
1214
            
1215
            // now, wrap container around the original node ... 
1216
            
1217
            obj.style.position = 'absolute';
1218
            container.appendChild(obj);
1219
            parentNode.insertBefore(container, replacement);
1220
            container.style.backgroundColor = 'transparent';
1221
            
1222
            container.style.padding = '0';
1223
            
1224
            filter = me.addFilter(obj, 'DXImageTransform.Microsoft.Matrix', "M11=1, M12=0, M21=0, M22=1, sizingMethod='auto expand'")
0 ignored issues
show
Unused Code introduced by
The variable filter seems to be never used. Consider removing it.
Loading history...
1225
            var bgImage = obj.currentStyle.backgroundImage.split("\"")[1];
0 ignored issues
show
Unused Code introduced by
The variable bgImage seems to be never used. Consider removing it.
Loading history...
1226
            /*
1227
            
1228
             
1229
            
1230
             if (bgImage) {
1231
            
1232
             
1233
            
1234
             var alphaFilter = me.addFilter(obj, "DXImageTransform.Microsoft.AlphaImageLoader", "src='" + bgImage + "', sizingMethod='scale'");
1235
            
1236
             
1237
            
1238
             alert(bgImage)
1239
            
1240
             
1241
            
1242
             alphaFilter.src = bgImage;
1243
            
1244
             
1245
            
1246
             sizingMethod = 'scale';
1247
            
1248
             
1249
            
1250
             obj.style.background = 'none';
1251
            
1252
             
1253
            
1254
             obj.style.backgroundImage = 'none';
1255
            
1256
             
1257
            
1258
             }
1259
            
1260
             
1261
            
1262
             */
1263
            
1264
        }
1265
        
1266
    }
1267
    
1268
    me.addFilter = function(obj, filterName, filterValue){
1269
        // now ... insert the filter so we can exploit its wonders
1270
        
1271
        var filter;
1272
        try {
1273
            filter = obj.filters.item(filterName);
1274
        } 
1275
        catch (ex) {
1276
            // dang! We have to go through all of them and make sure filter
1277
            // is set right before we add the new one.
1278
            
1279
            
1280
            var filterList = new MSFilterList(obj)
1281
            
1282
            filterList.fixFilterStyle();
1283
            
1284
            var comma = ", ";
1285
            
1286
            if (obj.filters.length == 0) {
1287
                comma = "";
1288
            }
1289
            
1290
            obj.style.filter += StringHelpers.sprintf("%sprogid:%s(%s)", comma, filterName, filterValue);
1291
            
1292
            filter = obj.filters.item(filterName);
1293
            
1294
        }
1295
        
1296
        return filter;
1297
    }
1298
    
1299
    
1300
    function degreesToRadians(degrees){
0 ignored issues
show
introduced by
The function degreesToRadians does not seem to be used and can be removed.
Loading history...
1301
        return (degrees - 360) * Math.PI / 180;
1302
    }
1303
    
1304
    me.findProperty = function(obj, type){
1305
        capType = type.capitalize();
0 ignored issues
show
Bug introduced by
The variable capType seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.capType.
Loading history...
1306
        
1307
        var r = cache[type]
1308
        if (!r) {
1309
        
1310
        
1311
            var style = obj.style;
1312
            
1313
            
1314
            var properties = [type, 'Moz' + capType, 'Webkit' + capType, 'O' + capType, 'filter'];
1315
            for (var i = 0; i < properties.length; i++) {
1316
                if (style[properties[i]] != null) {
1317
                    r = properties[i];
1318
                    break;
1319
                }
1320
            }
1321
            
1322
            if (r == 'filter' && document.body.filters == undefined) {
1323
                r = null;
1324
            }
1325
            cache[type] = r;
1326
        }
1327
        return r;
1328
    }
1329
    
1330
    /*
1331
     * "A point is a pair of space-separated values. The syntax supports numbers,
1332
     *  percentages or the keywords top, bottom, left and right for point values."
1333
     *  This keywords and percentages into pixel equivalents
1334
     */
1335
    me.parseCoordinate = function(value, max){
1336
        //Convert keywords
1337
        switch (value) {
1338
            case 'top':
1339
            case 'left':
1340
                return 0;
1341
            case 'bottom':
1342
            case 'right':
1343
                return max;
1344
            case 'center':
1345
                return max / 2;
1346
        }
1347
        
1348
        //Convert percentage
1349
        if (value.indexOf('%') != -1) 
1350
            value = parseFloat(value.substr(0, value.length - 1)) / 100 * max;
1351
        //Convert bare number (a pixel value)
1352
        else 
1353
            value = parseFloat(value);
1354
        if (isNaN(value)) 
1355
            throw Error("Unable to parse coordinate: " + value);
1356
        return value;
1357
    }
1358
    
1359
    me.applyCanvasGradient = function(el, gradient){
1360
    
1361
        var canvas = me.getCanvas();
1362
        var computedStyle = document.defaultView.getComputedStyle(el, null);
1363
        
1364
        canvas.width = parseInt(computedStyle.width) + parseInt(computedStyle.paddingLeft) + parseInt(computedStyle.paddingRight) + 1; // inserted by Zoltan
1365
        canvas.height = parseInt(computedStyle.height) + parseInt(computedStyle.paddingTop) + parseInt(computedStyle.paddingBottom) + 2; // 1 inserted by Zoltan
1366
        var ctx = canvas.getContext('2d');
1367
        
1368
        //Iterate over the gradients and build them up
1369
        
1370
        var canvasGradient;
1371
        // Linear gradient
1372
        if (gradient.type == 'linear') {
1373
        
1374
        
1375
            canvasGradient = ctx.createLinearGradient(me.parseCoordinate(gradient.x0, canvas.width), me.parseCoordinate(gradient.y0, canvas.height), me.parseCoordinate(gradient.x1, canvas.width), me.parseCoordinate(gradient.y1, canvas.height));
1376
        } // Radial gradient
1377
 else /*if(gradient.type == 'radial')*/ {
1378
            canvasGradient = ctx.createRadialGradient(me.parseCoordinate(gradient.x0, canvas.width), me.parseCoordinate(gradient.y0, canvas.height), gradient.r0, me.parseCoordinate(gradient.x1, canvas.width), me.parseCoordinate(gradient.y1, canvas.height), gradient.r1);
1379
        }
1380
        
1381
        //Add each of the color stops to the gradient
1382
        for (var i = 0; i < gradient.colorStops.length; i++) {
1383
            var cs = gradient.colorStops[i];
1384
            
1385
            canvasGradient.addColorStop(cs.stop, cs.color);
1386
        };
1387
        
1388
        //Paint the gradient
1389
        ctx.fillStyle = canvasGradient;
1390
        ctx.fillRect(0, 0, canvas.width, canvas.height);
1391
        
1392
        
1393
        //Apply the gradient to the selectedElement
1394
        el.style.backgroundImage = "url('" + canvas.toDataURL() + "')";
1395
        
1396
    }
1397
    
1398
}
1399
1400
function MSFilterList(node){
1401
    var me = this;
1402
    
1403
    me.list = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
1404
    me.node = node;
1405
    
1406
    var reFilterListSplitter = /[\s\S]*\([\s\S]*\)/g;
1407
    
1408
    var styleAttr = node.style;
1409
    
1410
    function init(){
1411
    
1412
        var filterCalls = styleAttr.filter.match(reFilterListSplitter);
1413
        
1414
        if (filterCalls != null) {
1415
        
1416
            for (var i = 0; i < filterCalls.length; i++) {
1417
                var call = filterCalls[i];
1418
                
1419
                me.list.push(new MSFilter(node, call));
1420
                
1421
            }
1422
        }
1423
        
1424
        
1425
    }
1426
    
1427
    me.toString = function(){
1428
        var sb = new StringBuffer();
1429
        
1430
        for (var i = 0; i < me.list.length; i++) {
1431
        
1432
            sb.append(me.list[i].toString());
1433
            if (i < me.list.length - 1) {
1434
                sb.append(',')
1435
            }
1436
        }
1437
        return sb.toString();
1438
    }
1439
    
1440
    
1441
    me.fixFilterStyle = function(){
1442
    
1443
        try {
1444
            me.node.style.filter = me.toString();
1445
        } 
1446
        catch (ex) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
1447
            // do nothing.
1448
        }
1449
        
1450
    }
1451
    
1452
    init();
1453
}
1454
1455
function MSFilter(node, filterCall){
1456
    var me = this;
1457
    
1458
    me.node = node;
1459
    me.filterCall = filterCall;
1460
    
1461
    var reFilterNameSplitter = /progid:([^\(]*)/g;
1462
    var reParameterName = /([a-zA-Z0-9]+\s*)=/g;
1463
    
1464
    
1465
    function init(){
1466
        me.name = me.filterCall.match(reFilterNameSplitter)[0].replace('progid:', '');
1467
        
1468
        //This may not be the best way to do this.
1469
        var parameterString = filterCall.split('(')[1].replace(')', '');
1470
        me.parameters = parameterString.match(reParameterName);
1471
        
1472
        for (var i = 0; i < me.parameters.length; i++) {
1473
            me.parameters[i] = me.parameters[i].replace('=', '');
1474
        }
1475
        
1476
    }
1477
    
1478
    me.toString = function(){
1479
    
1480
        var sb = new StringBuffer();
1481
        
1482
        sb.append(StringHelpers.sprintf('progid:%s(', me.name));
1483
        
1484
        for (var i = 0; i < me.parameters.length; i++) {
1485
            var param = me.parameters[i];
1486
            var filterObj = me.node.filters.item(me.name);
1487
            var paramValue = filterObj[param];
1488
            if (typeof(paramValue) == 'string') {
1489
                sb.append(StringHelpers.sprintf('%s="%s"', param, filterObj[param]));
1490
            } else {
1491
                sb.append(StringHelpers.sprintf('%s=%s', param, filterObj[param]));
1492
            }
1493
            
1494
            if (i != me.parameters.length - 1) {
1495
                sb.append(', ')
1496
            }
1497
        }
1498
        sb.append(')');
1499
        
1500
        return sb.toString();
1501
    }
1502
    
1503
    
1504
    
1505
    init();
1506
}
1507
1508
var implementation = new function(){
1509
    this.NONE = 0;
1510
    
1511
    // Native Support.
1512
    this.NATIVE = 1;
1513
    
1514
    // Vendor specific prefix implementations
1515
    this.MOZILLA = 2;
1516
    this.WEBKIT = 3;
1517
    this.IE = 4;
1518
    this.OPERA = 5;
1519
    
1520
    // Non CSS3 Workarounds 
1521
    this.CANVAS_WORKAROUND = 6;
1522
    this.FILTER_WORKAROUND = 7;
1523
    this.HEX_WORKAROUND = 8;
1524
}
1525
1526
var colorType = new function () {
1527
	this.BACKGROUND = 0;
1528
	this.FOREGROUND = 1;
1529
}
1530
1531
/*
1532
 * Extra helper routines
1533
 */
1534
if (!window.StringHelpers) {
1535
StringHelpers = new function(){
0 ignored issues
show
Bug introduced by
The variable StringHelpers seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.StringHelpers.
Loading history...
1536
    var me = this;
1537
    
1538
    // used by the String.prototype.trim()			
1539
    me.initWhitespaceRe = /^\s\s*/;
1540
    me.endWhitespaceRe = /\s\s*$/;
1541
    me.whitespaceRe = /\s/;
1542
    
1543
    /*******************************************************************************
1544
     * Function sprintf(format_string,arguments...) Javascript emulation of the C
1545
     * printf function (modifiers and argument types "p" and "n" are not supported
1546
     * due to language restrictions)
1547
     *
1548
     * Copyright 2003 K&L Productions. All rights reserved
1549
     * http://www.klproductions.com
1550
     *
1551
     * Terms of use: This function can be used free of charge IF this header is not
1552
     * modified and remains with the function code.
1553
     *
1554
     * Legal: Use this code at your own risk. K&L Productions assumes NO
1555
     * resposibility for anything.
1556
     ******************************************************************************/
1557
    me.sprintf = function(fstring){
1558
        var pad = function(str, ch, len){
1559
            var ps = '';
1560
            for (var i = 0; i < Math.abs(len); i++) 
1561
                ps += ch;
1562
            return len > 0 ? str + ps : ps + str;
1563
        }
1564
        var processFlags = function(flags, width, rs, arg){
1565
            var pn = function(flags, arg, rs){
1566
                if (arg >= 0) {
1567
                    if (flags.indexOf(' ') >= 0) 
1568
                        rs = ' ' + rs;
1569
                    else if (flags.indexOf('+') >= 0) 
1570
                        rs = '+' + rs;
1571
                } else 
1572
                    rs = '-' + rs;
1573
                return rs;
1574
            }
1575
            var iWidth = parseInt(width, 10);
1576
            if (width.charAt(0) == '0') {
1577
                var ec = 0;
1578
                if (flags.indexOf(' ') >= 0 || flags.indexOf('+') >= 0) 
1579
                    ec++;
1580
                if (rs.length < (iWidth - ec)) 
1581
                    rs = pad(rs, '0', rs.length - (iWidth - ec));
1582
                return pn(flags, arg, rs);
1583
            }
1584
            rs = pn(flags, arg, rs);
1585
            if (rs.length < iWidth) {
1586
                if (flags.indexOf('-') < 0) 
1587
                    rs = pad(rs, ' ', rs.length - iWidth);
1588
                else 
1589
                    rs = pad(rs, ' ', iWidth - rs.length);
1590
            }
1591
            return rs;
1592
        }
1593
        var converters = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
1594
        converters['c'] = function(flags, width, precision, arg){
1595
            if (typeof(arg) == 'number') 
1596
                return String.fromCharCode(arg);
1597
            if (typeof(arg) == 'string') 
1598
                return arg.charAt(0);
1599
            return '';
1600
        }
1601
        converters['d'] = function(flags, width, precision, arg){
1602
            return converters['i'](flags, width, precision, arg);
1603
        }
1604
        converters['u'] = function(flags, width, precision, arg){
1605
            return converters['i'](flags, width, precision, Math.abs(arg));
1606
        }
1607
        converters['i'] = function(flags, width, precision, arg){
1608
            var iPrecision = parseInt(precision);
1609
            var rs = ((Math.abs(arg)).toString().split('.'))[0];
1610
            if (rs.length < iPrecision) 
1611
                rs = pad(rs, ' ', iPrecision - rs.length);
1612
            return processFlags(flags, width, rs, arg);
1613
        }
1614
        converters['E'] = function(flags, width, precision, arg){
1615
            return (converters['e'](flags, width, precision, arg)).toUpperCase();
1616
        }
1617
        converters['e'] = function(flags, width, precision, arg){
1618
            iPrecision = parseInt(precision);
0 ignored issues
show
Bug introduced by
The variable iPrecision seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.iPrecision.
Loading history...
1619
            if (isNaN(iPrecision)) 
1620
                iPrecision = 6;
1621
            rs = (Math.abs(arg)).toExponential(iPrecision);
0 ignored issues
show
Bug introduced by
The variable rs seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rs.
Loading history...
1622
            if (rs.indexOf('.') < 0 && flags.indexOf('#') >= 0) 
1623
                rs = rs.replace(/^(.*)(e.*)$/, '$1.$2');
1624
            return processFlags(flags, width, rs, arg);
1625
        }
1626
        converters['f'] = function(flags, width, precision, arg){
1627
            iPrecision = parseInt(precision);
0 ignored issues
show
Bug introduced by
The variable iPrecision seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.iPrecision.
Loading history...
1628
            if (isNaN(iPrecision)) 
1629
                iPrecision = 6;
1630
            rs = (Math.abs(arg)).toFixed(iPrecision);
0 ignored issues
show
Bug introduced by
The variable rs seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rs.
Loading history...
1631
            if (rs.indexOf('.') < 0 && flags.indexOf('#') >= 0) 
1632
                rs = rs + '.';
1633
            return processFlags(flags, width, rs, arg);
1634
        }
1635
        converters['G'] = function(flags, width, precision, arg){
1636
            return (converters['g'](flags, width, precision, arg)).toUpperCase();
1637
        }
1638
        converters['g'] = function(flags, width, precision, arg){
1639
            iPrecision = parseInt(precision);
0 ignored issues
show
Bug introduced by
The variable iPrecision seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.iPrecision.
Loading history...
1640
            absArg = Math.abs(arg);
0 ignored issues
show
Bug introduced by
The variable absArg seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.absArg.
Loading history...
1641
            rse = absArg.toExponential();
0 ignored issues
show
Bug introduced by
The variable rse seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rse.
Loading history...
1642
            rsf = absArg.toFixed(6);
0 ignored issues
show
Bug introduced by
The variable rsf seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rsf.
Loading history...
1643
            if (!isNaN(iPrecision)) {
1644
                rsep = absArg.toExponential(iPrecision);
0 ignored issues
show
Bug introduced by
The variable rsep seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rsep.
Loading history...
1645
                rse = rsep.length < rse.length ? rsep : rse;
1646
                rsfp = absArg.toFixed(iPrecision);
0 ignored issues
show
Bug introduced by
The variable rsfp seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rsfp.
Loading history...
1647
                rsf = rsfp.length < rsf.length ? rsfp : rsf;
1648
            }
1649
            if (rse.indexOf('.') < 0 && flags.indexOf('#') >= 0) 
1650
                rse = rse.replace(/^(.*)(e.*)$/, '$1.$2');
1651
            if (rsf.indexOf('.') < 0 && flags.indexOf('#') >= 0) 
1652
                rsf = rsf + '.';
1653
            rs = rse.length < rsf.length ? rse : rsf;
0 ignored issues
show
Bug introduced by
The variable rs seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rs.
Loading history...
1654
            return processFlags(flags, width, rs, arg);
1655
        }
1656
        converters['o'] = function(flags, width, precision, arg){
1657
            var iPrecision = parseInt(precision);
1658
            var rs = Math.round(Math.abs(arg)).toString(8);
1659
            if (rs.length < iPrecision) 
1660
                rs = pad(rs, ' ', iPrecision - rs.length);
1661
            if (flags.indexOf('#') >= 0) 
1662
                rs = '0' + rs;
1663
            return processFlags(flags, width, rs, arg);
1664
        }
1665
        converters['X'] = function(flags, width, precision, arg){
1666
            return (converters['x'](flags, width, precision, arg)).toUpperCase();
1667
        }
1668
        converters['x'] = function(flags, width, precision, arg){
1669
            var iPrecision = parseInt(precision);
1670
            arg = Math.abs(arg);
1671
            var rs = Math.round(arg).toString(16);
1672
            if (rs.length < iPrecision) 
1673
                rs = pad(rs, ' ', iPrecision - rs.length);
1674
            if (flags.indexOf('#') >= 0) 
1675
                rs = '0x' + rs;
1676
            return processFlags(flags, width, rs, arg);
1677
        }
1678
        converters['s'] = function(flags, width, precision, arg){
1679
            var iPrecision = parseInt(precision);
1680
            var rs = arg;
1681
            if (rs.length > iPrecision) 
1682
                rs = rs.substring(0, iPrecision);
1683
            return processFlags(flags, width, rs, 0);
1684
        }
1685
        farr = fstring.split('%');
0 ignored issues
show
Bug introduced by
The variable farr seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.farr.
Loading history...
1686
        retstr = farr[0];
0 ignored issues
show
Bug introduced by
The variable retstr seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.retstr.
Loading history...
1687
        fpRE = /^([-+ #]*)(\d*)\.?(\d*)([cdieEfFgGosuxX])(.*)$/;
0 ignored issues
show
Bug introduced by
The variable fpRE seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.fpRE.
Loading history...
1688
        for (var i = 1; i < farr.length; i++) {
1689
            fps = fpRE.exec(farr[i]);
0 ignored issues
show
Bug introduced by
The variable fps seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.fps.
Loading history...
1690
            if (!fps) 
1691
                continue;
1692
            if (arguments[i] != null) 
1693
                retstr += converters[fps[4]](fps[1], fps[2], fps[3], arguments[i]);
1694
            retstr += fps[5];
1695
        }
1696
        return retstr;
1697
    }
1698
    
1699
    /**
1700
     * Take out the first comment inside a block of HTML
1701
     *
1702
     * @param {String} s - an HTML block
1703
     * @return {String} s - the HTML block uncommented.
1704
     */
1705
    me.uncommentHTML = function(s){
1706
        if (s.indexOf('-->') != -1 && s.indexOf('<!--') != -1) {
1707
            return s.replace("<!--", "").replace("-->", "");
1708
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1709
            return s;
1710
        }
1711
    }
1712
}
1713
}
1714
1715
if (!window.XMLHelpers) {
1716
1717
XMLHelpers = new function(){
0 ignored issues
show
Bug introduced by
The variable XMLHelpers seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.XMLHelpers.
Loading history...
1718
1719
    var me = this;
1720
    
1721
    /**
1722
     * Wrapper for XMLHttpRequest Object.  Grabbing data (XML and/or text) from a URL.
1723
     * Grabbing data from a URL. Input is one parameter, url. It returns a request
1724
     * object. Based on code from
1725
     * http://www.xml.com/pub/a/2005/02/09/xml-http-request.html.  IE caching problem
1726
     * fix from Wikipedia article http://en.wikipedia.org/wiki/XMLHttpRequest
1727
     *
1728
     * @param {String} url - the URL to retrieve
1729
     * @param {Function} processReqChange - the function/method to call at key events of the URL retrieval.
1730
     * @param {String} method - (optional) "GET" or "POST" (default "GET")
1731
     * @param {String} data - (optional) the CGI data to pass.  Default null.
1732
     * @param {boolean} isAsync - (optional) is this call asyncronous.  Default true.
1733
     *
1734
     * @return {Object} a XML request object.
1735
     */
1736
    me.getXMLHttpRequest = function(url, processReqChange) //, method, data, isAsync)
1737
    {
1738
        var argv = me.getXMLHttpRequest.arguments;
1739
        var argc = me.getXMLHttpRequest.arguments.length;
1740
        var httpMethod = (argc > 2) ? argv[2] : 'GET';
1741
        var data = (argc > 3) ? argv[3] : "";
1742
        var isAsync = (argc > 4) ? argv[4] : true;
1743
        
1744
        var req;
1745
        // branch for native XMLHttpRequest object
1746
        if (window.XMLHttpRequest) {
1747
            req = new XMLHttpRequest();
1748
            // branch for IE/Windows ActiveX version
1749
        } else if (window.ActiveXObject) {
1750
            try {
1751
                req = new ActiveXObject('Msxml2.XMLHTTP');
1752
            } 
1753
            catch (ex) {
1754
                req = new ActiveXObject("Microsoft.XMLHTTP");
1755
            }
1756
            // the browser doesn't support XML HttpRequest. Return null;
1757
        } else {
1758
            return null;
1759
        }
1760
        
1761
        if (isAsync) {
1762
            req.onreadystatechange = processReqChange;
1763
        }
1764
        
1765
        if (httpMethod == "GET" && data != "") {
1766
            url += "?" + data;
1767
        }
1768
        
1769
        req.open(httpMethod, url, isAsync);
1770
        
1771
        //Fixes IE Caching problem
1772
        req.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
1773
        req.send(data);
1774
        
1775
        return req;
1776
    }
1777
}
1778
}
1779
1780
1781
if (!window.CSSHelpers) {
1782
CSSHelpers = new function(){
0 ignored issues
show
Bug introduced by
The variable CSSHelpers seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.CSSHelpers.
Loading history...
1783
    var me = this;
1784
    
1785
    var blankRe = new RegExp('\\s');
1786
    
1787
	/*
1788
	 * getComputedStyle: code from http://blog.stchur.com/2006/06/21/css-computed-style/
1789
	 */
1790
	me.getComputedStyle = function(elem, style)
1791
	{
1792
	  var computedStyle;
1793
	  if (typeof elem.currentStyle != 'undefined')
1794
	    { computedStyle = elem.currentStyle; }
1795
	  else
1796
	    { computedStyle = document.defaultView.getComputedStyle(elem, null); }
1797
	
1798
	  return computedStyle[style];
1799
	}
1800
	
1801
	
1802
    /**
1803
     * Determines if an HTML object is a member of a specific class.
1804
     * @param {Object} obj - an HTML object.
1805
     * @param {Object} className - the CSS class name.
1806
     */
1807
    me.isMemberOfClass = function(obj, className){
1808
    
1809
        if (blankRe.test(className)) 
1810
            return false;
1811
        
1812
        var re = new RegExp(getClassReString(className), "g");
1813
        
1814
        return (re.test(obj.className));
1815
        
1816
        
1817
    }
1818
    
1819
    /**
1820
     * Make an HTML object be a member of a certain class.
1821
     *
1822
     * @param {Object} obj - an HTML object
1823
     * @param {String} className - a CSS class name.
1824
     */
1825
    me.addClass = function(obj, className){
1826
        if (blankRe.test(className)) {
1827
            return;
1828
        }
1829
        
1830
        // only add class if the object is not a member of it yet.
1831
        if (!me.isMemberOfClass(obj, className)) {
1832
            obj.className += " " + className;
1833
        }
1834
    }
1835
    
1836
    /**
1837
     * Make an HTML object *not* be a member of a certain class.
1838
     *
1839
     * @param {Object} obj - an HTML object
1840
     * @param {Object} className - a CSS class name.
1841
     */
1842
    me.removeClass = function(obj, className){
1843
    
1844
        if (blankRe.test(className)) {
1845
            return;
1846
        }
1847
        
1848
        
1849
        var re = new RegExp(getClassReString(className), "g");
1850
        
1851
        var oldClassName = obj.className;
1852
        
1853
        
1854
        if (obj.className) {
1855
            obj.className = oldClassName.replace(re, '');
1856
        }
1857
        
1858
        
1859
    }
1860
	
1861
	function getClassReString(className) {
1862
		return '\\s'+className+'\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className +'$';
1863
	}
1864
	
1865
	/**
1866
	 * Given an HTML element, find all child nodes of a specific class.
1867
	 * 
1868
	 * With ideas from Jonathan Snook 
1869
	 * (http://snook.ca/archives/javascript/your_favourite_1/)
1870
	 * Since this was presented within a post on this site, it is for the 
1871
	 * public domain according to the site's copyright statement.
1872
	 * 
1873
	 * @param {Object} obj - an HTML element.  If you want to search a whole document, set
1874
	 * 		this to the document object.
1875
	 * @param {String} className - the class name of the objects to return
1876
	 * @return {Array} - the list of objects of class cls. 
1877
	 */
1878
	me.getElementsByClassName = function (obj, className)
1879
	{
1880
		if (obj.getElementsByClassName) {
1881
			return DOMHelpers.nodeListToArray(obj.getElementsByClassName(className))
1882
		}
1883
		else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1884
			var a = [];
1885
			var re = new RegExp(getClassReString(className));
1886
			var els = DOMHelpers.getAllDescendants(obj);
1887
			for (var i = 0, j = els.length; i < j; i++) {
1888
				if (re.test(els[i].className)) {
1889
					a.push(els[i]);
1890
					
1891
				}
1892
			}
1893
			return a;
1894
		}
1895
	}
1896
    
1897
    /**
1898
     * Generates a regular expression string that can be used to detect a class name
1899
     * in a tag's class attribute.  It is used by a few methods, so I
1900
     * centralized it.
1901
     *
1902
     * @param {String} className - a name of a CSS class.
1903
     */
1904
    function getClassReString(className){
0 ignored issues
show
introduced by
The function getClassReString does not seem to be used and can be removed.
Loading history...
1905
        return '\\s' + className + '\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className + '$';
1906
    }
1907
    
1908
    
1909
}
1910
}
1911
1912
1913
/* 
1914
 * Adding trim method to String Object.  Ideas from
1915
 * http://www.faqts.com/knowledge_base/view.phtml/aid/1678/fid/1 and
1916
 * http://blog.stevenlevithan.com/archives/faster-trim-javascript
1917
 */
1918
String.prototype.trim = function(){
0 ignored issues
show
Compatibility Best Practice introduced by
You are extending the built-in type String. This may have unintended consequences on other objects using this built-in type. Consider subclassing instead.
Loading history...
1919
    var str = this;
1920
    
1921
    // The first method is faster on long strings than the second and 
1922
    // vice-versa.
1923
    if (this.length > 6000) {
1924
        str = this.replace(StringHelpers.initWhitespaceRe, '');
1925
        var i = str.length;
1926
        while (StringHelpers.whitespaceRe.test(str.charAt(--i))) 
0 ignored issues
show
introduced by
The while loop does not have a body. Maybe you have misplaced a semicolon. If you do wish to have a loop without a body, use an empty body {}.
Loading history...
1927
            ;
1928
        return str.slice(0, i + 1);
1929
    } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1930
        return this.replace(StringHelpers.initWhitespaceRe, '').replace(StringHelpers.endWhitespaceRe, '');
1931
    }
1932
    
1933
    
1934
};
1935
1936
if (!window.DOMHelpers) {
1937
1938
DOMHelpers = new function () {
0 ignored issues
show
Bug introduced by
The variable DOMHelpers seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.DOMHelpers.
Loading history...
1939
	var me = this;
1940
	
1941
	/**
1942
	 * Returns all children of an element. Needed if it is necessary to do
1943
	 * the equivalent of getElementsByTagName('*') for IE5 for Windows.
1944
	 * 
1945
	 * @param {Object} e - an HTML object.
1946
	 */
1947
	me.getAllDescendants = function(obj) {
1948
		return obj.all ? obj.all : obj.getElementsByTagName('*');
1949
	}
1950
	
1951
	/******
1952
	* Converts a DOM live node list to a static/dead array.  Good when you don't
1953
	* want the thing you are iterating in a for loop changing as the DOM changes.
1954
	* 
1955
	* @param {Object} nodeList - a node list (like one returned by document.getElementsByTagName)
1956
	* @return {Array} - an array of nodes.
1957
	* 
1958
	*******/
1959
	me.nodeListToArray = function (nodeList) 
1960
	{ 
1961
	    var ary = []; 
1962
	    for(var i=0, len = nodeList.length; i < len; i++) 
1963
	    { 
1964
	        ary.push(nodeList[i]); 
1965
	    } 
1966
	    return ary; 
1967
	} 
1968
}
1969
}
1970
1971
//+ Jonas Raoni Soares Silva
1972
//@ http://jsfromhell.com/string/capitalize [v1.0]
1973
1974
String.prototype.capitalize = function(){ //v1.0
1975
    return this.charAt(0).toUpperCase() + this.substr(1);
1976
    
1977
};
1978
1979
1980
/*
1981
 *  stringBuffer.js - ideas from
1982
 *  http://www.multitask.com.au/people/dion/archives/000354.html
1983
 */
1984
function StringBuffer(){
1985
    var me = this;
1986
    
1987
    var buffer = [];
1988
    
1989
    
1990
    me.append = function(string){
1991
        buffer.push(string);
1992
        return me;
1993
    }
1994
    
1995
    me.appendBuffer = function(bufferToAppend){
1996
        buffer = buffer.concat(bufferToAppend);
1997
    }
1998
    
1999
    me.toString = function(){
2000
        return buffer.join("");
2001
    }
2002
    
2003
    me.getLength = function(){
2004
        return buffer.length;
2005
    }
2006
    
2007
    me.flush = function(){
2008
        buffer.length = 0;
2009
    }
2010
    
2011
}
2012
2013
/**
2014
 * A class to parse color values
2015
 * @author Stoyan Stefanov <[email protected]> (with modifications)
2016
 * @link   http://www.phpied.com/rgb-color-parser-in-javascript/
2017
 * @license Use it if you like it
2018
 */
2019
function RGBColor(color_string){
2020
2021
    var me = this;
2022
    
2023
    
2024
    
2025
    me.ok = false;
2026
    
2027
    // strip any leading #
2028
    if (color_string.charAt(0) == '#') { // remove # if any
2029
        color_string = color_string.substr(1, 6);
2030
    }
2031
    
2032
    color_string = color_string.replace(/ /g, '');
2033
    color_string = color_string.toLowerCase();
2034
    
2035
    // before getting into regexps, try simple matches
2036
    // and overwrite the input
2037
    var simple_colors = {
2038
        aliceblue: 'f0f8ff',
2039
        antiquewhite: 'faebd7',
2040
        aqua: '00ffff',
2041
        aquamarine: '7fffd4',
2042
        azure: 'f0ffff',
2043
        beige: 'f5f5dc',
2044
        bisque: 'ffe4c4',
2045
        black: '000000',
2046
        blanchedalmond: 'ffebcd',
2047
        blue: '0000ff',
2048
        blueviolet: '8a2be2',
2049
        brown: 'a52a2a',
2050
        burlywood: 'deb887',
2051
        cadetblue: '5f9ea0',
2052
        chartreuse: '7fff00',
2053
        chocolate: 'd2691e',
2054
        coral: 'ff7f50',
2055
        cornflowerblue: '6495ed',
2056
        cornsilk: 'fff8dc',
2057
        crimson: 'dc143c',
2058
        cyan: '00ffff',
2059
        darkblue: '00008b',
2060
        darkcyan: '008b8b',
2061
        darkgoldenrod: 'b8860b',
2062
        darkgray: 'a9a9a9',
2063
        darkgreen: '006400',
2064
        darkkhaki: 'bdb76b',
2065
        darkmagenta: '8b008b',
2066
        darkolivegreen: '556b2f',
2067
        darkorange: 'ff8c00',
2068
        darkorchid: '9932cc',
2069
        darkred: '8b0000',
2070
        darksalmon: 'e9967a',
2071
        darkseagreen: '8fbc8f',
2072
        darkslateblue: '483d8b',
2073
        darkslategray: '2f4f4f',
2074
        darkturquoise: '00ced1',
2075
        darkviolet: '9400d3',
2076
        deeppink: 'ff1493',
2077
        deepskyblue: '00bfff',
2078
        dimgray: '696969',
2079
        dodgerblue: '1e90ff',
2080
        feldspar: 'd19275',
2081
        firebrick: 'b22222',
2082
        floralwhite: 'fffaf0',
2083
        forestgreen: '228b22',
2084
        fuchsia: 'ff00ff',
2085
        gainsboro: 'dcdcdc',
2086
        ghostwhite: 'f8f8ff',
2087
        gold: 'ffd700',
2088
        goldenrod: 'daa520',
2089
        gray: '808080',
2090
        green: '008000',
2091
        greenyellow: 'adff2f',
2092
        honeydew: 'f0fff0',
2093
        hotpink: 'ff69b4',
2094
        indianred: 'cd5c5c',
2095
        indigo: '4b0082',
2096
        ivory: 'fffff0',
2097
        khaki: 'f0e68c',
2098
        lavender: 'e6e6fa',
2099
        lavenderblush: 'fff0f5',
2100
        lawngreen: '7cfc00',
2101
        lemonchiffon: 'fffacd',
2102
        lightblue: 'add8e6',
2103
        lightcoral: 'f08080',
2104
        lightcyan: 'e0ffff',
2105
        lightgoldenrodyellow: 'fafad2',
2106
        lightgrey: 'd3d3d3',
2107
        lightgreen: '90ee90',
2108
        lightpink: 'ffb6c1',
2109
        lightsalmon: 'ffa07a',
2110
        lightseagreen: '20b2aa',
2111
        lightskyblue: '87cefa',
2112
        lightslateblue: '8470ff',
2113
        lightslategray: '778899',
2114
        lightsteelblue: 'b0c4de',
2115
        lightyellow: 'ffffe0',
2116
        lime: '00ff00',
2117
        limegreen: '32cd32',
2118
        linen: 'faf0e6',
2119
        magenta: 'ff00ff',
2120
        maroon: '800000',
2121
        mediumaquamarine: '66cdaa',
2122
        mediumblue: '0000cd',
2123
        mediumorchid: 'ba55d3',
2124
        mediumpurple: '9370d8',
2125
        mediumseagreen: '3cb371',
2126
        mediumslateblue: '7b68ee',
2127
        mediumspringgreen: '00fa9a',
2128
        mediumturquoise: '48d1cc',
2129
        mediumvioletred: 'c71585',
2130
        midnightblue: '191970',
2131
        mintcream: 'f5fffa',
2132
        mistyrose: 'ffe4e1',
2133
        moccasin: 'ffe4b5',
2134
        navajowhite: 'ffdead',
2135
        navy: '000080',
2136
        oldlace: 'fdf5e6',
2137
        olive: '808000',
2138
        olivedrab: '6b8e23',
2139
        orange: 'ffa500',
2140
        orangered: 'ff4500',
2141
        orchid: 'da70d6',
2142
        palegoldenrod: 'eee8aa',
2143
        palegreen: '98fb98',
2144
        paleturquoise: 'afeeee',
2145
        palevioletred: 'd87093',
2146
        papayawhip: 'ffefd5',
2147
        peachpuff: 'ffdab9',
2148
        peru: 'cd853f',
2149
        pink: 'ffc0cb',
2150
        plum: 'dda0dd',
2151
        powderblue: 'b0e0e6',
2152
        purple: '800080',
2153
        red: 'ff0000',
2154
        rosybrown: 'bc8f8f',
2155
        royalblue: '4169e1',
2156
        saddlebrown: '8b4513',
2157
        salmon: 'fa8072',
2158
        sandybrown: 'f4a460',
2159
        seagreen: '2e8b57',
2160
        seashell: 'fff5ee',
2161
        sienna: 'a0522d',
2162
        silver: 'c0c0c0',
2163
        skyblue: '87ceeb',
2164
        slateblue: '6a5acd',
2165
        slategray: '708090',
2166
        snow: 'fffafa',
2167
        springgreen: '00ff7f',
2168
        steelblue: '4682b4',
2169
        tan: 'd2b48c',
2170
        teal: '008080',
2171
        metle: 'd8bfd8',
2172
        tomato: 'ff6347',
2173
        turquoise: '40e0d0',
2174
        violet: 'ee82ee',
2175
        violetred: 'd02090',
2176
        wheat: 'f5deb3',
2177
        white: 'ffffff',
2178
        whitesmoke: 'f5f5f5',
2179
        yellow: 'ffff00',
2180
        yellowgreen: '9acd32'
2181
    };
2182
    for (var key in simple_colors) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
2183
        if (color_string == key) {
2184
            color_string = simple_colors[key];
2185
        }
2186
    }
2187
    // emd of simple type-in colors
2188
    
2189
    // array of color definition objects
2190
    var color_defs = [{
2191
        re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
2192
        example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
2193
        process: function(bits){
2194
            return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
2195
        }
2196
    }, {
2197
        re: /^(\w{2})(\w{2})(\w{2})$/,
2198
        example: ['#00ff00', '336699'],
2199
        process: function(bits){
2200
            return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)];
2201
        }
2202
    }, {
2203
        re: /^(\w{1})(\w{1})(\w{1})$/,
2204
        example: ['#fb0', 'f0f'],
2205
        process: function(bits){
2206
            return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)];
2207
        }
2208
    }, {
2209
        re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(0{0,1}\.\d{1,}|0\.{0,}0*|1\.{0,}0*)\)$/,
2210
        example: ['rgba(123, 234, 45, 22)', 'rgba(255, 234,245, 34)'],
2211
        process: function(bits){
2212
            return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]), parseFloat(bits[4])];
2213
        }
2214
    }, {
2215
        re: /^hsla\((\d{1,3}),\s*(\d{1,3}%),\s*(\d{1,3}%),\s*(0{0,1}\.\d{1,}|0\.{0,}0*|1\.{0,}0*)\)$/,
2216
        example: ['hsla(0,100%,50%,0.2)'],
2217
        process: function(bits){
2218
        	var result = hsl2rgb(parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]), parseFloat(bits[4]));
0 ignored issues
show
Bug introduced by
The call to hsl2rgb seems to have too many arguments starting with parseFloat(bits.4).
Loading history...
2219
        	
2220
        	return [result.r, result.g, result.b, parseFloat(bits[4])];
2221
            
2222
        }
2223
    }, {
2224
        re: /^hsl\((\d{1,3}),\s*(\d{1,3}%),\s*(\d{1,3}%)\)$/,
2225
        example: ['hsl(0,100%,50%)'],
2226
        process: function(bits){
2227
        	var result = hsl2rgb(parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]), 1);
0 ignored issues
show
Bug introduced by
The call to hsl2rgb seems to have too many arguments starting with 1.
Loading history...
2228
        	
2229
        	return [result.r, result.g, result.b, 1];
2230
            
2231
        }
2232
    }];
2233
    
2234
    // search through the definitions to find a match
2235
    for (var i = 0; i < color_defs.length; i++) {
2236
        var re = color_defs[i].re;
2237
        var processor = color_defs[i].process;
2238
        var bits = re.exec(color_string);
2239
        if (bits) {
2240
            channels = processor(bits);
0 ignored issues
show
Bug introduced by
The variable channels seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.channels.
Loading history...
2241
            me.r = channels[0];
2242
            me.g = channels[1];
2243
            me.b = channels[2];
2244
            me.a = channels[3];
2245
            me.ok = true;
2246
        }
2247
        
2248
    }
2249
    
2250
    // validate/cleanup values
2251
    me.r = (me.r < 0 || isNaN(me.r)) ? 0 : ((me.r > 255) ? 255 : me.r);
2252
    me.g = (me.g < 0 || isNaN(me.g)) ? 0 : ((me.g > 255) ? 255 : me.g);
2253
    me.b = (me.b < 0 || isNaN(me.b)) ? 0 : ((me.b > 255) ? 255 : me.b);
2254
    
2255
    
2256
    
2257
    me.a = (isNaN(me.a)) ? 1 : ((me.a > 255) ? 255 : (me.a < 0) ? 0 : me.a);
2258
    
2259
    
2260
    
2261
    // some getters
2262
    me.toRGB = function(){
2263
        return 'rgb(' + me.r + ', ' + me.g + ', ' + me.b + ')';
2264
    }
2265
    
2266
    // some getters
2267
    me.toRGBA = function(){
2268
        return 'rgba(' + me.r + ', ' + me.g + ', ' + me.b + ', ' + me.a + ')';
2269
    }
2270
    
2271
    /**
2272
     * Converts an RGB color value to HSV. Conversion formula
2273
     * adapted from http://en.wikipedia.org/wiki/HSV_color_space.
2274
     * Assumes r, g, and b are contained in the set [0, 255] and
2275
     * returns h, s, and v in the set [0, 1].
2276
     *
2277
     * This routine by Michael Jackson (not *that* one),
2278
     * from http://www.mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
2279
     *
2280
     * @param   Number  r       The red color value
2281
     * @param   Number  g       The green color value
2282
     * @param   Number  b       The blue color value
2283
     * @return  Array           The HSV representation
2284
     */
2285
    me.toHSV = function(){
2286
        var r = me.r / 255, g = me.g / 255, b = me.b / 255;
2287
        var max = Math.max(r, g, b), min = Math.min(r, g, b);
2288
        var h, s, v = max;
2289
        
2290
        var d = max - min;
2291
        s = max == 0 ? 0 : d / max;
2292
        
2293
        if (max == min) {
2294
            h = 0; // achromatic
2295
        } else {
2296
            switch (max) {
2297
                case r:
2298
                    h = (g - b) / d + (g < b ? 6 : 0);
2299
                    break;
2300
                case g:
2301
                    h = (b - r) / d + 2;
2302
                    break;
2303
                case b:
2304
                    h = (r - g) / d + 4;
2305
                    break;
2306
            }
2307
            h /= 6;
2308
        }
2309
        
2310
        return {
2311
            h: h,
2312
            s: s,
2313
            v: v
2314
        };
2315
    }
2316
    
2317
    /*
2318
     * hsl2rgb from http://codingforums.com/showthread.php?t=11156 
2319
     * code by Jason Karl Davis (http://www.jasonkarldavis.com)
2320
     */
2321
    function hsl2rgb(h, s, l) {
2322
		var m1, m2, hue;
2323
		var r, g, b
2324
		s /=100;
2325
		l /= 100;
2326
		if (s == 0)
2327
			r = g = b = (l * 255);
2328
		else {
2329
			if (l <= 0.5)
2330
				m2 = l * (s + 1);
2331
			else
2332
				m2 = l + s - l * s;
2333
			m1 = l * 2 - m2;
2334
			hue = h / 360;
2335
			r = HueToRgb(m1, m2, hue + 1/3);
2336
			g = HueToRgb(m1, m2, hue);
2337
			b = HueToRgb(m1, m2, hue - 1/3);
2338
		}
2339
		return {r: Math.round(r), g: Math.round(g), b: Math.round(b)}; 
2340
	}
2341
	
2342
	function HueToRgb(m1, m2, hue) {
2343
		var v;
2344
		if (hue < 0)
2345
			hue += 1;
2346
		else if (hue > 1)
2347
			hue -= 1;
2348
	
2349
		if (6 * hue < 1)
2350
			v = m1 + (m2 - m1) * hue * 6;
2351
		else if (2 * hue < 1)
2352
			v = m2;
2353
		else if (3 * hue < 2)
2354
			v = m1 + (m2 - m1) * (2/3 - hue) * 6;
2355
		else
2356
			v = m1;
2357
	
2358
		return 255 * v;
2359
	}
2360
    
2361
    
2362
    
2363
    me.toHex = function(){
2364
        var r = me.r.toString(16);
2365
        var g = me.g.toString(16);
2366
        var b = me.b.toString(16);
2367
        
2368
        var a = Math.floor((me.a * 255)).toString(16);
2369
        
2370
        if (r.length == 1) 
2371
            r = '0' + r;
2372
        if (g.length == 1) 
2373
            g = '0' + g;
2374
        if (b.length == 1) 
2375
            b = '0' + b;
2376
        
2377
        
2378
        if (a == 'ff') {
2379
            a = '';
2380
        } else if (a.length == 1) {
2381
            a = '0' + a;
2382
        }
2383
        return '#' + a + r + g + b;
2384
    }
2385
    
2386
    
2387
    
2388
}
2389
2390
document.write('<style type="text/css">.cssSandpaper-initiallyHidden { visibility: hidden;} </style>');
2391
2392
2393
2394
EventHelpers.addPageLoadEvent('cssSandpaper.init')
2395
2396