[Community-cvs] www/theme/js behaviour.js, NONE, 1.1 divstyle.js, NONE, 1.1 gradients.js, NONE, 1.1
admin at helixcommunity.org admin at helixcommunity.orgUpdate of /cvsroot/community/www/theme/js
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv11660
Added Files:
behaviour.js divstyle.js gradients.js
Log Message:
added divstyle, gradients, behaviour for gradient left hand nav background
--- NEW FILE: behaviour.js ---
/*
Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work
of Simon Willison (see comments by Simon below).
Description:
Uses css selectors to apply javascript behaviours to enable
unobtrusive javascript in html documents.
Usage:
var myrules = {
'b.someclass' : function(element){
element.onclick = function(){
alert(this.innerHTML);
}
},
'#someid u' : function(element){
element.onmouseover = function(){
this.innerHTML = "BLAH!";
}
}
};
Behaviour.register(myrules);
// Call Behaviour.apply() to re-apply the rules (if you
// update the dom, etc).
License:
This file is entirely BSD licensed.
More information:
http://ripcord.co.nz/behaviour/
*/
var Behaviour = {
list : new Array,
register : function(sheet){
Behaviour.list.push(sheet);
},
start : function(){
Behaviour.addLoadEvent(function(){
Behaviour.apply();
});
},
apply : function(){
for (h=0;sheet=Behaviour.list[h];h++){
for (selector in sheet){
list = document.getElementsBySelector(selector);
if (!list){
continue;
}
for (i=0;element=list[i];i++){
sheet[selector](element);
}
}
}
},
addLoadEvent : function(func){
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
}
Behaviour.start();
/*
The following code is Copyright (C) Simon Willison 2004.
document.getElementsBySelector(selector)
- returns an array of element objects from the current document
matching the CSS selector. Selectors can contain element names,
class names and ids and can be nested. For example:
elements = document.getElementsBySelect('div#main p a.external')
Will return an array of all 'a' elements with 'external' in their
class attribute that are contained inside 'p' elements that are
contained inside the 'div' element which has id="main"
New in version 0.4: Support for CSS2 and CSS3 attribute selectors:
See http://www.w3.org/TR/css3-selectors/#attribute-selectors
Version 0.4 - Simon Willison, March 25th 2003
-- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows
-- Opera 7 fails
*/
function getAllChildren(e) {
// Returns all children of element. Workaround required for IE5/Windows. Ugh.
return e.all ? e.all : e.getElementsByTagName('*');
}
document.getElementsBySelector = function(selector) {
// Attempt to fail gracefully in lesser browsers
if (!document.getElementsByTagName) {
return new Array();
}
// Split selector in to tokens
var tokens = selector.split(' ');
var currentContext = new Array(document);
for (var i = 0; i < tokens.length; i++) {
token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
if (token.indexOf('#') > -1) {
// Token is an ID selector
var bits = token.split('#');
var tagName = bits[0];
var id = bits[1];
var element = document.getElementById(id);
if (tagName && element.nodeName.toLowerCase() != tagName) {
// tag with that ID not found, return false
return new Array();
}
// Set currentContext to contain just this element
currentContext = new Array(element);
continue; // Skip to next token
}
if (token.indexOf('.') > -1) {
// Token contains a class selector
var bits = token.split('.');
var tagName = bits[0];
var className = bits[1];
if (!tagName) {
tagName = '*';
}
// Get elements matching tag, filter them for class selector
var found = new Array;
var foundCount = 0;
for (var h = 0; h < currentContext.length; h++) {
var elements;
if (tagName == '*') {
elements = getAllChildren(currentContext[h]);
} else {
elements = currentContext[h].getElementsByTagName(tagName);
}
for (var j = 0; j < elements.length; j++) {
found[foundCount++] = elements[j];
}
}
currentContext = new Array;
var currentContextIndex = 0;
for (var k = 0; k < found.length; k++) {
if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
currentContext[currentContextIndex++] = found[k];
}
}
continue; // Skip to next token
}
// Code to deal with attribute selectors
if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
var tagName = RegExp.$1;
var attrName = RegExp.$2;
var attrOperator = RegExp.$3;
var attrValue = RegExp.$4;
if (!tagName) {
tagName = '*';
}
// Grab all of the tagName elements within current context
var found = new Array;
var foundCount = 0;
for (var h = 0; h < currentContext.length; h++) {
var elements;
if (tagName == '*') {
elements = getAllChildren(currentContext[h]);
} else {
elements = currentContext[h].getElementsByTagName(tagName);
}
for (var j = 0; j < elements.length; j++) {
found[foundCount++] = elements[j];
}
}
currentContext = new Array;
var currentContextIndex = 0;
var checkFunction; // This function will be used to filter the elements
switch (attrOperator) {
case '=': // Equality
checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
break;
case '~': // Match one of space seperated words
checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
break;
case '|': // Match start with value followed by optional hyphen
checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
break;
case '^': // Match starts with value
checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
break;
case '$': // Match ends with value - fails with "Warning" in Opera 7
checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
break;
case '*': // Match ends with value
checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
break;
default :
// Just test for existence of attribute
checkFunction = function(e) { return e.getAttribute(attrName); };
}
currentContext = new Array;
var currentContextIndex = 0;
for (var k = 0; k < found.length; k++) {
if (checkFunction(found[k])) {
currentContext[currentContextIndex++] = found[k];
}
}
// alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
continue; // Skip to next token
}
if (!currentContext[0]){
return;
}
// If we get here, token is JUST an element (not a class or ID selector)
tagName = token;
var found = new Array;
var foundCount = 0;
for (var h = 0; h < currentContext.length; h++) {
var elements = currentContext[h].getElementsByTagName(tagName);
for (var j = 0; j < elements.length; j++) {
found[foundCount++] = elements[j];
}
}
currentContext = found;
}
return currentContext;
}
/* That revolting regular expression explained
/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
\---/ \---/\-------------/ \-------/
| | | |
| | | The value
| | ~,|,^,$,* or =
| Attribute
Tag
*/
--- NEW FILE: gradients.js ---
/*
Author: Oliver Steele
Copyright: Copyright 2006 Oliver Steele. All rights reserved.
License: MIT License (Open Source)
Homepage: http://osteele.com/sources/javascript
Download: http://osteele.com/sources/javascript/gradients.js
Docs: http://osteele.com/sources/javascript/docs/gradients
Example: http://osteele.com/sources/javascript/demos/gradients.html
Blog: http://osteele.com/archives/2006/03/javascript-gradient-roundrects
Created: 2006-03-12
Modified: 2006-03-20
== Overview
+gradients.js+ adds rounded rectangular gradients to a page,
without the use of images.
+gradients.js+ uses the +canvas+ tag if it is available. Otherwise
it creates the gradient through the use of +div+ tags.
A gradient can be applied to an element procedurally, via JavaScript,
or (with the use of the {DivStyle library}[http://osteele.com/sources/javascript/docs/divstyle])
through the use of CSS embedded within an element's +div+ tags.
== JavaScript API
<tt>OSGradient.applyGradient(properties, element)</tt> applies
a gradient to +element+.
+properties+ is a hash of properties:
* +gradient-start-color+: gradient start color (top); required
* +gradient-end-color+: gradient end color (bottom); default white
* +border-radius+: rounded corner radius; default zero
Colors must be specified as the hex number +0xrrggbb+,
e.g. +0xff0000+ for red. (The Divstyle API, below, allows the use
of symbolic color names.) +border-radius+ must be specified as a
Number of pixels, e.g. +25+ (not +25px+).
=== Usage
<html>
<head>
<script type="text/javascript" src="gradients.js"></script>
</head>
<body>
<div id="elt">Some text</div>
<script type="text/javascript">
var elt = document.getElementById('elt');
var style = {'gradient-start-color': 0x0000ff,
'border-radius': 25};
OSGradient.applyGradient(style, elt);
</script>
</body>
</html>
=== DivStyle API
If the +divstyle.js+ and +behaviour.js+ files are included, you can
also specify a gradient using CSS syntax inside a +div+ tag with
class +style+. CSS selectors within the div style can select
multiple tags, and multiple selectors can add properties to a single
element.
+divstyle.js+ is available from http://osteele.com/sources/javascript/.
+behaviour.js+ is available from http://bennolan.com/behaviour/.
(That's the British spelling of "behaviour".)
=== Usage
<html>
<head>
<script type="text/javascript" src="behaviour.js"></script>
<script type="text/javascript" src="divstyle.js"></script>
<script type="text/javascript" src="gradients.js"></script>
<style type="text/css">
.style {display: none}
#red, .blue-grade {width: 100px}
</style>
</head>
<body>
<div class="style">
#red {gradient-start-color: red}
.blue-grade {gradient-start-color: blue}
.rounded {border-radius: 10}
</div>
<div id="red">Red</div>
<div class="blue-grade">Blue...</div>
<div class="blue-grade rounded">...rounded</div>
</body>
</html>
=== Limitations
The +style+ div can contain a subset of CSS syntax. This
subset is described in the {documentation for <div>divstyle.js</div>}[http://osteele.com/sources/javascript/docs/divstyle].
*/
/*
* Gradient package
*/
function OSGradient() {
this.initialize.apply(this, arguments);
}
OSGradient.applyGradient = function(style, element) {
var gradient = new OSGradient(style);
gradient.applyGradient(element);
};
// Create a gradient for each element that has a divStyle.
// +divstyle.js+ sets the divStyles automatically. This function does
// nothing if +divstyle.js+ has not been loaded, unless JavaScript
// code has explicitly set the +divStyle+ properties of any HTML
// Elements.
OSGradient.applyGradients = function() {
try {DivStyle.initialize()} catch(e) {}
var elements = document.getElementsByTagName('*');
for (var i = 0, e; e = elements[i++]; ) {
var style = e.divStyle;
if (style && style.gradientStartColor)
OSGradient.applyGradient(style, e);
}
};
// Number of bands necessary for a smooth gradient, by component.
// The max of the color range and height are pinned to this.
OSGradient.maxBands = [192, 192, 96];
// The following properties need to be set in order for style.zIndex
// to work in IE. This function is called the first time that a
// gradient is attached to an element.
OSGradient.setBodyStyle = function() {
OSGradient.setBodyStyle = function() {}
var style = document.body.style;
style.position = 'relative';
style.left = 0;
style.top = 0;
style.zIndex = 0;
};
//
// Instance methods
//
OSGradient.prototype.initialize = function(style) {
this.style = style;
};
OSGradient.prototype.applyGradient = function(e) {
var width = e.offsetWidth, height = e.offsetHeight;
var gradientElement = (this.createCanvasGradient(e, width, height) ||
this.createGradientElement(width, height));
OSGradient.setBodyStyle();
this.attachGradient(e, gradientElement);
};
OSGradient.prototype.createCanvasGradient = function(e, width, height) {
var canvas = document.createElement('canvas');
var ctx;
// Return null if canvas isn't supported. The caller will
// fall back on divs.
try {ctx = canvas.getContext('2d')} catch (e) {return null}
// Safari requires the following prior to rendering
e.appendChild(canvas);
if (navigator.appVersion.match(/Konqueror|Safari|KHTML/))
canvas.style.position = 'fixed';
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
var style = this.style;
var c0 = style['gradient-start-color'];
var c1 = style['gradient-end-color'];
var r = style['border-radius'];
ctx.beginPath();
ctx.moveTo(0,r);
//arcTo() produces NS_ERROR_NOT_IMPLEMENT in Firefox 1.5; use arc() instead:
//ctx.arcTo(0,0,r,0,r);
ctx.arc(r,r,r,Math.PI,-Math.PI/2,false);
ctx.lineTo(width-r,0);
//ctx.arcTo(width,0,width,r,r);
ctx.arc(width-r,r,r,-Math.PI/2,0,false);
ctx.lineTo(width,height-r);
//ctx.arcTo(width,height,width-r,height,r);
ctx.arc(width-r,height-r,r,0,Math.PI/2,false);
ctx.lineTo(r,height);
//ctx.arcTo(0,height,0,height-r,r);
ctx.arc(r,height-r,r,Math.PI/2,Math.PI,false);
ctx.clip();
var g = ctx.fillStyle = ctx.createLinearGradient(0,0,0,height);
g.addColorStop(0, OSUtils.color.long2css(c0));
g.addColorStop(1, OSUtils.color.long2css(c1));
ctx.rect(0,0,width,height);
ctx.fill();
return canvas;
};
OSGradient.prototype.makeSpan = function(x, y, width, height, color, opacity) {
var properties = {position: 'absolute',
left: x+'px',
top: y+'px',
width: width+'px',
height: height+'px',
// for IE:
'font-size': 1,
'line-height': 0,
background: color};
if (opacity != undefined) properties.opacity = opacity;
var style = [];
for (var p in properties)
style.push(p + ':' + String(properties[p]));
// IE requires the
return '<div style="'+style.join(';')+'"> </div>';
};
OSGradient.prototype.createGradientElement = function(width, height) {
var style = this.style;
var c0 = style['gradient-start-color'];
var c1 = style['gradient-end-color'];
var r = style['border-radius'];
function xAt(y) {
var dy = Math.max(r-y, y-(height-r));
if (dy >= 0)
return r - Math.sqrt(r*r-dy*dy);
return 0;
};
var bands = 0;
for (var shift = 24; (shift -= 8) >= 0; )
bands = Math.max(bands,
1+Math.min(Math.abs(c0 - c1) >> shift & 255,
OSGradient.maxBands[2-shift/8]));
bands = Math.max(bands, height);
var transitions = [];
for (var i = 0; i <= bands; i++)
transitions.push(Math.floor(i * height / bands));
if (r) {
var tops = [];
var bottoms = [];
var lastx = null;
for (var y = 0; y <= r; y++) {
var x = Math.ceil(xAt(y));
if (x == lastx) continue;
lastx = x;
transitions.push(y);
transitions.push(height-y);
}
transitions.sort(function(a,b){return a-b});
}
OSUtils.Array.removeDuplicates(transitions);
var spans = [];
for (var i = 0; i < transitions.length-1; i++) {
var y = transitions[i];
var h = transitions[i+1] - y;
var x = Math.ceil(xAt(y));
var color = OSUtils.color.interpolate(c0, c1, y/height);
spans.push(this.makeSpan(x, y, width-2*x, h,
OSUtils.color.long2css(color)));
}
var g = document.createElement('div');
g.innerHTML = spans.join('');
if (true) {
g.style.position = 'absolute';
g.style.left = '0px';
g.style.top = '0px';
g.style.width = "100%";
g.style.height = '100%';
g.style.zIndex = -1;
}
return g;
};
OSGradient.prototype.attachGradient = function(parent, gradient) {
gradient.style.position = 'absolute';
gradient.style.left = '0px';
gradient.style.top = '0px';
// Setting the canvas's dimensions erases its contents in Firefox,
// even though it's the SAME DIMENSIONS.
if (gradient.width != parent.offsetWidth)
gradient.width = parent.offsetWidth;
if (gradient.height != parent.offsetHeight)
gradient.height = parent.offsetHeight;
gradient.style.zIndex = -1;
if (!parent.style.position.match(/absolute|relative/i))
parent.style.position = 'relative';
// The canvas parent has already been set, for Safari.
if (gradient.parentNode != parent)
parent.appendChild(gradient);
};
/*
* Utilities
*/
try {OSUtils} catch(e) {OSUtils = {}}
if (!OSUtils.color) {OSUtils.color = {}}
if (!OSUtils.Array) {OSUtils.Array = {}}
// 0x123456 -> "#123456"
OSUtils.color.long2css = function(n) {
var a = "0123456789ABCDEF";
var s = '#';
for (var i = 24; (i -= 4) >= 0; )
s += a.charAt((n>>i) & 0xf);
return s;
};
// (a,b,0)->a; (a,b,1)->b; a and b are rrggbb color numbers.
OSUtils.color.interpolate = function(a, b, s) {
var n = 0;
for (var i = 24; (i -= 8) >= 0; ) {
var ca = (a >> i) & 0xff;
var cb = (b >> i) & 0xff;
var cc = Math.floor(ca*(1-s) + cb*s);
n |= cc << i;
}
return n;
};
// Modify +ar+ in-place to remove consecutive duplicates.
OSUtils.Array.removeDuplicates = function(ar) {
var i = 0, j = 0;
while (j < ar.length) {
var v = ar[i] = ar[j++];
if (!i || ar[i-1] != v) i++;
}
ar.length = i;
return ar;
};
/*
* Initialization
*/
// If divstyle.js has been included, define these:
try {
DivStyle.defineProperty('gradient-start-color', 'color');
DivStyle.defineProperty('gradient-end-color', 'color', 0xffffff);
DivStyle.defineProperty('border-radius', 'number', 0);
} catch(e) {}
if (window.addEventListener) {
window.addEventListener('load', OSGradient.applyGradients, false);
} else if (window.attachEvent) {
window.attachEvent('onload', OSGradient.applyGradients);
} else {
window.onload = (function() {
var nextfn = window.onload || function(){};
return function() {
OSGradient.applyGradients();
nextfn();
}
})();
}
--- NEW FILE: divstyle.js ---
/*
Author: Oliver Steele
Copyright: Copyright 2006 Oliver Steele. All rights reserved.
License: MIT License (Open Source)
Homepage: http://osteele.com/sources/javascript
Download: http://osteele.com/sources/javascript/divstyle.js
Docs: http://osteele.com/sources/javascript/docs/divstyle
Example: http://osteele.com/sources/javascript/demos/gradients.html
Blog: http://osteele.com/archives/2006/03/javascript-gradient-roundrects
Created: 2006-03-16
Modified: 2006-03-21
+divstyle.js+ adds a user-extensible style mechanism, that parallels
CSS styles but can contain properties that are not in the CSS
standard.
When +divstyle.js+ is loaded, <tt><div></tt> tags in the HTML
document that have a class of "+style+" can contain (a subset of)
CSS, but with nonstandard property names. Each element that is
selected by a "div CSS" rule has a +.divStyle+ property. The value
of this property is a map of property names to values.
See the {Gradient library}[http://osteele.com/sources/javascript/docs/gradients]
for an example of how this can be used.
== Usage
<html>
<head>
<-- include the divstyle implementation: -->
<script type="text/javascript" src="behaviour.js"></script>
<script type="text/javascript" src="divstyle.js"></script>
</head>
<body>
<!-- define the styles: -->
<div class="style">
#e1, .myclass {my-property: 'string', prop1: 123}
.myclass {prop2: #ff0000}
</div>
<!-- define the elements. The styles are applied to these. -->
<div id="e1"></div>
<div id="e2" class="myclass"></div>
<div id="e3" class="myclass"></div>
<!-- access the styles from JavaScript: -->
<script type="text/javascript">
alert(document.getElementById('e1').divStyle.myProperty);
alert(document.getElementById('e2').divStyle.prop1);
alert(document.getElementById('e3').divStyle.prop2);
var rules = document.divStylesheet.cssRules; // all the rules
</script>
</body>
</html>
== Caveats
You can't put the style content in comments. (Safari strips comments
from the DOM before JavaScript sees them.)
CSS simple selectors are limited to at most one modifier
(+div.c1+, but not +div.c1.c2+).
Quotes inside an attribute name selector may not work.
The CSS parser is incomplete, and doesn't recover from many parse
errors.
*/
/*
* Utilities
*/
try {OSUtils} catch(e) {OSUtils = {}}
if (!OSUtils.Array) {OSUtils.Array = {}}
if (!OSUtils.Hash) {OSUtils.Hash = {}}
OSUtils.Array.union = function (a, b) {
var c = new Array(a.length);
for (var i = 0; i < a.length; i++)
c[i] = a[i];
for (var i = 0; i < b.length; i++)
if (!OSUtils.Array.contains(a, b[i]))
c.push(b[i]);
return c;
};
OSUtils.Array.contains = function (ar, e) {
for (var i = 0; i < ar.length; i++)
if (ar[i] == e)
return true;
return false;
};
OSUtils.Hash.update = function(a, b) {
for (var p in b)
a[p] = b[p];
return a;
};
/*
* DivStyle package
*/
var DivStyle = {};
DivStyle.getStyleSheet = function() {
if (document.divStylesheet) return document.divStylesheet;
var styleSheet = new DivStyle.CSSStyleSheet;
var elements = document.getElementsByTagName('div');
for (var i = 0, e; e = elements[i++]; )
if (e.className.match(/\bstyle\b/i)) {
e.style.display = 'none';
styleSheet.addRules(e.innerHTML);
}
return document.divStylesheet = styleSheet;
};
DivStyle.applyStyles = function () {
var rules = DivStyle.getStyleSheet().cssRules;
for (var ri = 0, rule; rule = rules[ri++];) {
var elements = rule.getSelectedElements();
for (var ei = 0, e; e = elements[ei++]; ) {
e.divStyle = e.divStyle || OSUtils.Hash.update({}, DivStyle.defaultProperties);
OSUtils.Hash.update(e.divStyle, rule.style);
}
}
};
DivStyle.propertyDefinitions = {};
DivStyle.defaultProperties = {};
DivStyle.defineProperty = function(name, type, defaultValue) {
DivStyle.propertyDefinitions[name] = {type: type, defaultValue: defaultValue};
if (defaultValue != undefined)
DivStyle.defaultProperties[name] = defaultValue;
};
DivStyle.parseProperty = function(name, value) {
var definition = DivStyle.propertyDefinitions[name];
var type = (definition||{}).type;
switch (type) {
case 'color':
return CSSParser.parseColor(value);
case 'number':
return parseInt(value);
}
return value;
};
/*
* CSSStyleSheet
*/
DivStyle.CSSStyleSheet = function () {
this.cssRules = [];
};
DivStyle.CSSStyleSheet.prototype.addRules = function (text) {
var parser = new CSSParser(new CSSBuilder(this));
parser.parse(text);
};
DivStyle.CSSStyleSheet.prototype.addRule = function(selector, properties) {
this.cssRules.push(new DivStyle.CSSRule(selector, properties));
};
/*
* CSSRule
*/
DivStyle.CSSRule = function(selectors, properties) {
var newProperties = {};
for (var p in properties)
if (p.match(/-/)) {
var words = p.split(/-/);
for (var i = 0, w; w = words[i]; i++)
if (i && w)
words[i] = w.charAt(0).toUpperCase() + w.slice(1);
newProperties[words.join('')] = properties[p];
}
for (var p in newProperties)
properties[p] = newProperties[p];
this.selectors = selectors;
this.style = properties;
};
DivStyle.CSSRule.prototype.getSelectedElements = function() {
var selectors = this.selectors;
var results = [];
for (var i = 0, selector; selector = selectors[i++]; ) {
var selectorText = this.makeSelectorString(selector);
var elements = document.getElementsBySelector(selectorText) || [];
results = OSUtils.Array.union(results, elements);
}
return results;
};
// make a string that behaviour.js can interpret
DivStyle.CSSRule.prototype.makeSelectorString = function(selector) {
var s = [];
for (var i = 0; i < selector.length; i++) {
var sel = selector[i];
if (s.length && s[s.length-1].match(/^\w/) && sel.match(/^\w/))
s.push(' ');
if (sel.match(/^'.*'$/))
sel = '"' + sel.slice(1, sel.length-1) + '"';
s.push(sel);
}
return s.join('');
};
/*
* Parser
*/
function CSSParser(builder) {
this.builder = builder;
};
CSSParser.ColorNames = {
aqua: 0x00FFFF,
black: 0x000000,
blue: 0x0000FF,
fuchsia: 0xFF00FF,
gray: 0x808080,
green: 0x008000,
lime: 0x00FF00,
maroon: 0x800000,
navy: 0x000080,
olive: 0x808000,
purple: 0x800080,
red: 0xFF0000,
silver: 0xC0C0C0,
teal: 0x008080,
white: 0xFFFFFF,
yellow: 0xFFFF00
};
CSSParser.parseColor = function(value) {
if (value.charAt(0) == '#') {
var n = parseInt(value.slice(1), 16);
switch (!isNaN(n) && value.length-1) {
case 3:
return ((n & 0xf00) << 8 | (n & 0xf0) << 4 | (n & 0xf)) * 17;
case 6:
return n;
}
}
if (CSSParser.ColorNames[value])
return CSSParser.ColorNames[value];
error('invalid color: ' + value);
return 0x000000;
};
CSSParser.TOKEN_PATTERNS = {
IDENT: /^\w[\w\d-]*/,
STRING: /^"([^\\\"]|\\.)*"|'([^\\\']|\\.)*'/,
HASH: /^#[\w\d-]+/,
INCLUDES: /~=/,
DASHMATCH: /\|=/,
SKIP_WS: /^\s+/m,
SKIP_LC: /^\/\/.*/,
SKIP_BC: /^\/\*([^\*]|\*[^\/])*\*\//m
};
// Codes:
// '+': append to token list
// null: ignore
// Errors are ignored.
CSSParser.transitions = {
initial: {
'IDENT': ['+'],
'HASH': ['+'],
'*': ['+'],
'.': ['+'],
'[': ['+', 'attrib'],
',': ['setSelector'],
'{': ['endSelector', 'propertyName']
},
attrib: {
'IDENT': ['+'],
'STRING': ['+'],
'=': ['+'],
'INCLUDES': ['+'],
'DASHMATCH': ['+'],
']': ['+', 'initial']
},
propertyName: {
IDENT: ['setPropertyName', 'propertyColon'],
'}': ['endProperties', 'initial']
},
propertyColon: {
':': [null, 'propertyValue'],
';': [null, 'propertyName'], // error
'}': ['endProperties', 'initial'] // error
},
propertyValue: {
IDENT: ['+'],
HASH: ['+'],
STRING: ['+'],
';': ['setPropertyValue', 'propertyName'],
'}': ['endPropertiesWithValue', 'initial']
}
};
CSSParser.prototype.nextToken = function () {
var slice = this.text.slice(this.i);
if (!slice) return null;
for (var p in CSSParser.TOKEN_PATTERNS) {
var m = slice.match(CSSParser.TOKEN_PATTERNS[p]);
if (m && m.index == 0) {
this.i += m[0].length;
if (p.match(/^SKIP/))
return this.nextToken();
var value = m[0];
if (p == 'NUMBER')
value = parseInt(value);
return {type: p, value: value};
}
}
var c = this.text.charAt(this.i++);
return {type: c, value: c};
};
CSSParser.prototype.parse = function(text) {
this.text = text;
this.i = 0;
var state = 'initial';
var values = [];
while (true) {
var token = this.nextToken();
if (!token) return;
var entry = CSSParser.transitions[state][token.type];
if (!entry) throw 'parse error at state ' + state + ', token ' + token;
var action = entry[0];
var nextState = entry[1] || state;
if (action == '+')
values.push(token.value);
else if (action) {
var fn = this.builder[action];
if (!fn) throw 'unknown action ' + action;
fn.apply(this.builder, [values, token.value]);
values = [];
}
state = nextState;
}
};
/*
* Parser
*/
function CSSBuilder(styleSheet) {
this.styleSheet = styleSheet;
this.beginRule();
}
CSSBuilder.prototype.beginRule = function() {
this.selectors = [];
this.properties = {};
};
CSSBuilder.prototype.endSelector = function(values) {
this.selectors.push(values);
};
CSSBuilder.prototype.setPropertyName = function(_, name) {
this.propertyName = name;
};
CSSBuilder.prototype.setPropertyValue = function(values) {
var name = this.propertyName;
var value = values.join(' ');
this.properties[name] = DivStyle.parseProperty(name, value);
};
CSSBuilder.prototype.endProperties = function() {
this.styleSheet.addRule(this.selectors, this.properties);
this.beginRule();
};
CSSBuilder.prototype.endPropertiesWithValue = function(values) {
this.setPropertyValue(values);
this.endProperties();
};
/*
* Initialization
*/
DivStyle.initialize = function() {
DivStyle.initialize = function () {}
DivStyle.applyStyles();
};
if (window.addEventListener) {
window.addEventListener('load', DivStyle.initialize, false);
} else if (window.attachEvent) {
window.attachEvent('onload', DivStyle.initialize);
} else {
window.onload = (function() {
var nextfn = window.onload || function(){};
return function() {
DivStyle.initialize();
nextfn();
}
})();
}