WP File Manager
Current Path:
/
home
/
article
/
www
/
squelettes
/
scripts
/
Name
Action
..
css3-multi-column.js
Edit
jquery.stylish-select.min.js
Edit
moo.js
Edit
selectref.js
Edit
smoothscroll.js
Edit
Editing: css3-multi-column.js
// CSS3MultiColumn - a javascript implementation of the CSS3 multi-column module // v1.02 beta - Jan 08 2008 // Copyright (c) 2005 Cdric Savarese <pro@4213miles.com> // This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/> // For additional information, see : http://www.csscripting.com/ // Supported Properties: // column-count // column-width // column-gap // column-rule // Unsupported Properties: // column-rule-width (use column-rule instead) // column-rule-style (use column-rule instead) // column-rule-color (use column-rule instead) // column-span // column-width-policy // column-space-distribution function CSS3MultiColumn() { //alert('Development Version'); var cssCache = new Object(); var splitableTags = new Array('P','DIV', 'SPAN', 'BLOCKQUOTE','ADDRESS','PRE', 'A', 'EM', 'I', 'STRONG', 'B', 'CITE', 'OL', 'UL', 'LI' ); var pseudoCSSRules = new Object(); var ut = new CSS3Utility(); var debug = ut.debug; if(document.location.search.match('mode=debug')) var isDebug = true; else var isDebug = false; var bestSplitPoint = null; var secondSplitPoint = null; var secondSplitBottom = 0; var documentReady = false; // INITIALIZATION ut.XBrowserAddEventHandler(window,'load',function() { documentReady = true; processElements(); } ); loadStylesheets(); // CSS PARSING // -------------------------------------------------------------------------------------- // loadStylesheets: // Loop through the stylesheets collection and load the css text into the cssCache object function loadStylesheets() { if(document.styleSheets) { // Firefox & IE // initialize cache for(var i=0;i < document.styleSheets.length;i++) { cssCache[document.styleSheets[i].href] = false; } // load css in the cache for(var i=0;i < document.styleSheets.length;i++) { loadCssCache(document.styleSheets[i], 'parseStylesheets'); } } else if (document.getElementsByTagName) { // OPERA var Lt = document.getElementsByTagName('link'); // initialize cache for(var i= 0; i<Lt.length; i++) { cssCache[Lt[i].href] = false; } // load css in the cache for(var i= 0; i<Lt.length; i++) { loadCssCache(Lt[i], 'parseStylesheets'); } //var St = document.getElementsByTagName('style'); } } // loadCssCache // Asynchronous function. Call the 'callback' function when done. function loadCssCache(s, callback) { if (s.href && s.cssText) { cssCache[s.href] = s.cssText; eval(callback)(); } if (s.href && typeof XMLHttpRequest!='undefined') { var xmlhttp = new XMLHttpRequest(); //if(xmlhttp.abort) xmlhttp.abort(); xmlhttp.onreadystatechange = function() { if(xmlhttp.readyState == 4) { if(typeof xmlhttp.status == 'undefined' || xmlhttp.status == 200 || xmlhttp.status == 304 ) { cssCache[s.href] = xmlhttp.responseText; eval(callback)(); } } } xmlhttp.open("GET", s.href, true); //synchrone transaction crashes Opera 8.01 xmlhttp.send(null); } } // parseStylesheets: // Iterates the cssCache object and send the serialized css to the mini-parser. function parseStylesheets() { var allDone = true; for(var i in cssCache) { if(cssCache[i]!=false) parseStylesheet(cssCache[i]); else allDone = false; } if(allDone) { processElements(); } } // parseStylesheet: // Loads the pseudoCSSRules object with the values for column-count, column-width, column-gap... function parseStylesheet(cssText) { // Retrieving column-count property var cc = new ut.getPseudoCssRules('column-count',cssText); for(var i=0; cc && i<cc.cssRules.length;i++) { if(!pseudoCSSRules[cc.cssRules[i].selectorText]) pseudoCSSRules[cc.cssRules[i].selectorText] = new Object(); pseudoCSSRules[cc.cssRules[i].selectorText]['column-count'] = cc.cssRules[i].value; } // Retrieving column-width property cc = new ut.getPseudoCssRules('column-width',cssText); for(var i=0; cc && i<cc.cssRules.length;i++) { if(!pseudoCSSRules[cc.cssRules[i].selectorText]) pseudoCSSRules[cc.cssRules[i].selectorText] = new Object(); pseudoCSSRules[cc.cssRules[i].selectorText]['column-width'] = cc.cssRules[i].value; } // Retrieving column-gap property cc = new ut.getPseudoCssRules('column-gap',cssText); for(var i=0; cc && i<cc.cssRules.length;i++) { if(!pseudoCSSRules[cc.cssRules[i].selectorText]) pseudoCSSRules[cc.cssRules[i].selectorText] = new Object(); pseudoCSSRules[cc.cssRules[i].selectorText]['column-gap'] = cc.cssRules[i].value; } // Retrieving column-rule property cc = new ut.getPseudoCssRules('column-rule',cssText); for(var i=0; cc && i<cc.cssRules.length;i++) { if(!pseudoCSSRules[cc.cssRules[i].selectorText]) pseudoCSSRules[cc.cssRules[i].selectorText] = new Object(); pseudoCSSRules[cc.cssRules[i].selectorText]['column-rule'] = cc.cssRules[i].value; } } // COLUMN PROCESSING function processElements() { // wait for page to finish loading if(!documentReady) return; for(var i in pseudoCSSRules) { debug(i + ' cc:' + pseudoCSSRules[i]['column-count'] + ' cw:' + pseudoCSSRules[i]['column-width'] + ' cr:' + pseudoCSSRules[i]['column-rule'] + ' cg:' + pseudoCSSRules[i]['column-gap']); var affectedElements = ut.cssQuery(i); for(var j=0;j<affectedElements.length;j++) { //debug("affected element: " + affectedElements[j].tagName + ' [' + affectedElements[j].id + ' / ' + affectedElements[j].className + ']'); processElement(affectedElements[j], pseudoCSSRules[i]['column-count'], pseudoCSSRules[i]['column-width'], pseudoCSSRules[i]['column-gap'], pseudoCSSRules[i]['column-rule']); } } } function processElement(affectedElement, column_count, column_width, column_gap, column_rule ) { //affectedElement.style.visibility = 'hidden'; var widthUnit; var width; var column_rule_width = 0; // Get available width // see http://www.csscripting.com/css-multi-column/dom-width-height.php // offsetWidth & scrollWidth are the only consistent values across browsers. // offsetWidth includes border, padding and scroll bars // scrollWidth includes border and padding // clientWidth when available includes padding only. // see http://msdn.microsoft.com/workshop/author/om/measuring.asp if(affectedElement.clientWidth && affectedElement.clientWidth != 0) { var padding; if(affectedElement.currentStyle) { padding = parseInt(affectedElement.currentStyle.paddingLeft.replace(/[\D]*/gi,"")) + parseInt(affectedElement.currentStyle.paddingRight.replace(/[\D]*/gi,"")) } else if (document.defaultView && document.defaultView.getComputedStyle) { padding = parseInt(document.defaultView.getComputedStyle(affectedElement,"").getPropertyValue("padding-left").replace(/[\D]*/gi,"")) + parseInt(document.defaultView.getComputedStyle(affectedElement,"").getPropertyValue("padding-left").replace(/[\D]*/gi,"")) //padding = parseInt(window.getComputedStyle(affectedElement,"").getPropertyValue("padding-left").replace(/[\D]*/gi,"")) + parseInt(window.getComputedStyle(affectedElement,"").getPropertyValue("padding-left").replace(/[\D]*/gi,"")) } if (isNaN(padding)) padding = 0; width = (affectedElement.clientWidth - padding).toString() + "px"; } else if(affectedElement.scrollWidth) { var borderWidth; var padding; if(affectedElement.currentStyle) { padding = parseInt(affectedElement.currentStyle.paddingLeft.replace(/[\D]*/gi,"")) + parseInt(affectedElement.currentStyle.paddingRight.replace(/[\D]*/gi,"")) } else if (document.defaultView && document.defaultView.getComputedStyle) { padding = parseInt(document.defaultView.getComputedStyle(affectedElement,"").getPropertyValue("padding-left").replace(/[\D]*/gi,"")) + parseInt(document.defaultView.getComputedStyle(affectedElement,"").getPropertyValue("padding-left").replace(/[\D]*/gi,"")) } if (isNaN(padding)) padding = 0; if(affectedElement.currentStyle) { borderWidth = parseInt(affectedElement.currentStyle.borderLeftWidth.replace(/[\D]*/gi,"")) + parseInt(affectedElement.currentStyle.borderRightWidth.replace(/[\D]*/gi,"")) } else if (document.defaultView && document.defaultView.getComputedStyle) { borderWidth = parseInt(document.defaultView.getComputedStyle(affectedElement,"").getPropertyValue("border-left-width").replace(/[\D]*/gi,"")) + parseInt(document.defaultView.getComputedStyle(affectedElement,"").getPropertyValue("border-right-width").replace(/[\D]*/gi,"")) } if (isNaN(borderWidth)) borderWidth = 0; width = (affectedElement.scrollWidth - padding - borderWidth).toString() + "px"; } else width = "99%"; // ever used? var availableWidth = parseInt(width.replace(/[\D]*/gi,"")); // Get width unit if(!column_width || column_width == 'auto') widthUnit = width.replace(/[\d]*/gi,""); else widthUnit = column_width.replace(/[\d]*/gi,""); if(!widthUnit) widthUnit = "px"; if(!column_gap) { // Compute column spacing (column_gap) if(widthUnit=="%") column_gap = 1; //%; else column_gap = 15; //px; } else { column_gap = parseInt(column_gap.replace(/[\D]*/gi,"")); } if(column_rule && column_rule != 'none') { column_gap = Math.floor(column_gap/2); // we add half the original column_gap to the column_rule_width to fix the column_width count below. column_rule_width = column_gap + parseInt(column_rule.substring(column_rule.search(/\d/),column_rule.search(/\D/))); } if(!column_width || column_width == 'auto') {// Compute columns' width column_width = (availableWidth-((column_gap+column_rule_width)*(column_count-1))) / column_count; } else { column_width = parseInt(column_width.replace(/[\D]*/gi,"")) if(!column_count || column_count == 'auto') {// Compute column count column_count = Math.floor(availableWidth / (column_width + column_gap)); } } column_width -= 1; // Create a wrapper var wrapper = document.createElement('div'); //affectedElement.tagName var pn = affectedElement.parentNode; wrapper = pn.insertBefore(wrapper, affectedElement); var elem = pn.removeChild(affectedElement); elem = wrapper.appendChild(elem); //wrapper.style.border = "1px solid #F00"; wrapper.className = elem.className; elem.className = ""; // since all columns will be left-floating we need to clear the floats after them. //wrapper.style.overflow = 'auto'; // Assign the content element a random Id ? elem.id = ut.randomId(); // Adjust content's width and float the element elem.style.width = column_width.toString() + widthUnit; //elem.style.padding = "0"; //elem.style.margin = "0"; if(typeof elem.style.styleFloat != 'undefined') elem.style.styleFloat = "left"; if(typeof elem.style.cssFloat != 'undefined') elem.style.cssFloat = "left"; // Compute Desired Height var newHeight = Math.floor(elem.offsetHeight / column_count)+14; if(!wrapper.id) wrapper.id = ut.randomId(); // Find split points (j is the max # of attempts to find a good height with no unsplittable element on the split point. var j=1; for(var i=1; i < column_count && elem && j < (column_count + 5) ; i++) { bestSplitPoint = null; secondSplitPoint = null; secondSplitBottom = 0; findSplitPoint(elem, newHeight*i, wrapper); if(isDebug) bestSplitPoint.style.border = "1px solid #00FF00"; if(bestSplitPoint && !isElementSplitable(bestSplitPoint)) { newHeight = getElementRelativeTop(bestSplitPoint, wrapper) + bestSplitPoint.offsetHeight + 10; i=1; // reset the height. Try again. debug('reset new Height = '+newHeight + ' relativetop=' + getElementRelativeTop(bestSplitPoint, wrapper) + ' offsetHeight= ' + bestSplitPoint.offsetHeight ); } else if (!bestSplitPoint) { debug("No split point found with " + newHeight); } j++; } //wrapper.style.minHeight = newHeight + 'px'; //if(document.all && !window.opera) //wrapper.style.height = newHeight + 'px'; debug('<table><tr><td>Avail. Width</td><td>'+availableWidth+'</td><td>Units</td><td>'+widthUnit+'</td></tr><tr><td>column_width</td><td>'+column_width+'</td><td>column_count</td><td>'+column_count+'</td></tr><tr><td>column_gap</td><td>'+column_gap+'</td><td>column_rule</td><td>'+column_rule+'</td></tr><tr><td>New Height</td><td>' + newHeight + '</td><td></td><td></td></tr></table>' ); for(var i=1; i < column_count && elem; i++) { // Find the split point (a child element, sitting on the column split point) bestSplitPoint = null; secondSplitPoint = null; secondSplitBottom = 0; findSplitPoint(elem, newHeight, wrapper); if(bestSplitPoint && isElementSplitable(bestSplitPoint) && elem.id != bestSplitPoint.id) { var splitE = bestSplitPoint; if(isDebug) secondSplitPoint.style.border = "1px dotted #00F"; } else { var splitE = secondSplitPoint; } if(!splitE) { debug("<hr />No split point found for " + elem.tagName + ' ' + newHeight); return; } // DEBUG ONLY: SHOW SPLIT ELEMENT //debug("split top=" + getElementRelativeTop(splitE, wrapper)); if(isDebug) splitE.style.border = "1px solid #F00"; // END DEBUG ONLY: SHOW SPLIT ELEMENT // Create New Column var newCol = elem.cloneNode(false); newCol.id = ut.randomId(); // Insert new column in the document elem.parentNode.insertBefore(newCol, elem.nextSibling); // Add the column_gap newCol.style.paddingLeft = column_gap + widthUnit; // Add the column_rule if(column_rule && column_rule != 'none') { newCol.style.borderLeft = column_rule; elem.style.paddingRight = column_gap + widthUnit; } if(document.all && !window.opera) elem.style.height = newHeight+'px'; elem.style.minHeight = newHeight+'px'; // Move all elements after the element to be splitted (splitE) to the new column var insertPoint = createNodeAncestors(splitE,elem, newCol, 'append'); var refElement = splitE; while(refElement && refElement.id != elem.id ) { var littleSib = refElement.nextSibling; while(littleSib) { moveNode(littleSib, elem, newCol); littleSib = refElement.nextSibling; } refElement = refElement.parentNode; } var strippedLine = splitElement(splitE, newHeight - getElementRelativeTop(splitE, wrapper), elem, newCol); // cleaning emptied elements var pn = splitE.parentNode; while(pn && pn.id != elem.id) { var n = pn.firstChild; while(n) { if((n.nodeType==1 && n.childNodes.length == 0) || (n.nodeType==3 && n.nodeValue.replace(/[\u0020\u0009\u000A]*/,'') == "")) { pn.removeChild(n); n = pn.firstChild; } else { n = n.nextSibling; } } pn = pn.parentNode; } // if text-align is justified, insert to force the justify if(strippedLine) { splitE = elem.lastChild; if(splitE && (document.defaultView && document.defaultView.getComputedStyle(splitE,'').getPropertyValue('text-align')=='justify') || (splitE.currentStyle && splitE.currentStyle.textAlign == 'justify')) { var txtFiller = document.createTextNode(' ' + strippedLine.replace(/./g,"\u00a0")); // var filler = document.createElement('span'); splitE.appendChild(filler); filler.style.lineHeight="1px"; filler.appendChild(txtFiller); } } // move on to split the newly added column elem = newCol; } if(elem) {//mainly to set the column rule at the right height. if(document.all && !window.opera) elem.style.height = newHeight+'px'; elem.style.minHeight = newHeight+'px'; } var clearFloatDiv = document.createElement('div'); clearFloatDiv.style.clear = "left"; // < bug in Safari 1.3 ? (duplicates content) clearFloatDiv.appendChild(document.createTextNode(' ')); wrapper.appendChild(clearFloatDiv); if(navigator.userAgent.toLowerCase().indexOf('safari') + 1) wrapper.innerHTML+=' '; // forces redraw in safari and fixes bug above. //wrapper.style.visibility = 'visible'; } // Find the deepest splitable element that sits on the split point. function findSplitPoint(n, newHeight, wrapper) { if (n.nodeType==1) { var top = getElementRelativeTop(n, wrapper); var bot = top+n.offsetHeight; if(top < newHeight && bot > newHeight) { bestSplitPoint = n; if(isElementSplitable(n)) { for(var i=0;i<n.childNodes.length;i++) { findSplitPoint(n.childNodes[i], newHeight, wrapper); } } return; } if(bot <= newHeight && bot >= secondSplitBottom) { secondSplitBottom = bot; secondSplitPoint = n; } } return; } function isElementSplitable(n) { if(n.tagName) { var tagName = n.tagName.toUpperCase(); for(var i=0;i<splitableTags.length;i++) if(tagName==splitableTags[i]) return true; } return false; } function splitElement(n, targetHeight, col1, col2) { var cn = n.lastChild; while(cn) { // if the child node is a text node if(cn.nodeType==3) { var strippedText = "dummmy"; var allStrippedText = ""; // the +2 is for tweaking.. allowing lines to fit more easily while(n.offsetHeight > targetHeight+2 && strippedText!="") { // remove lines of text until the splittable element reaches the targeted height or we run out of text. strippedText = stripOneLine(cn); allStrippedText = strippedText + allStrippedText; } if(allStrippedText!="") { var insertPoint = createNodeAncestors(cn,col1,col2,'insertBefore'); insertPoint.insertBefore(document.createTextNode(allStrippedText), insertPoint.firstChild); } if(cn.nodeValue=="") { cn.parentNode.removeChild(cn); } else break; } else { // move element var insertPoint = createNodeAncestors(cn,col1,col2,'insertBefore'); insertPoint.insertBefore(cn.parentNode.removeChild(cn), insertPoint.firstChild); } cn = n.lastChild; } return strippedText; // returns the last line of text removed (used later for forcing the justification) } // stripOneLine() // This function removes exactly one line to // any element containing text // and returns the removed text as a string. function stripOneLine (n) { // get the text node while(n && n.nodeType != 3) n = n.firstChild; if(!n) return; // get the height of the element var e = n.parentNode; var h = e.offsetHeight; if(!h) { //debug('no height for: ' + e.tagName); return ""; } // get the text as a string var str = n.nodeValue; // remove a word from the end of the string // until the height of the element changes // (ie. a line has been removed) var wIdx= n.nodeValue.lastIndexOf(' '); while(wIdx!=-1 && e.offsetHeight == h) { n.nodeValue = n.nodeValue.substr(0, wIdx); wIdx = n.nodeValue.lastIndexOf(' '); if(wIdx==-1) wIdx = n.nodeValue.lastIndexOf('\n'); //debug(e.offsetHeight + ' ' + h + ' text=' + n.nodeValue + ' wIdx= ' + wIdx); } if(e.offsetHeight == h) n.nodeValue = ""; // returns the removed text return str.substr(n.nodeValue.length); } // method= 'append'/'insertBefore', relative to col2 function createNodeAncestors(n,col1,col2,method) { var ancestors = new Array; var insertNode = col2; var pn = n.parentNode; while(pn && pn.id != col1.id) { ancestors[ancestors.length] = pn; if(!pn.id) pn.id = ut.randomId(); pn = pn.parentNode; } for (var i=ancestors.length-1; i >= 0; i--) { for(var j=0; j < insertNode.childNodes.length && (insertNode.childNodes[j].nodeType==3 || !insertNode.childNodes[j].className.match(ancestors[i].id+'-css3mc')); j++); if(j==insertNode.childNodes.length) { // Ancestor node not found, needs to be created. if(method=='append') insertNode = insertNode.appendChild(document.createElement(ancestors[i].tagName)); else insertNode = insertNode.insertBefore(document.createElement(ancestors[i].tagName),insertNode.firstChild); insertNode.className = ancestors[i].className+ ' ' + ancestors[i].id + '-css3mc'; insertNode.style.marginTop = "0"; insertNode.style.paddingTop = "0"; if(insertNode.tagName.toUpperCase() == 'OL' && n.nodeType == 1 && n.tagName.toUpperCase() =='LI') { var prevsib = n.previousSibling; var count=0; while(prevsib) { if(prevsib.nodeType==1 && prevsib.tagName.toUpperCase() == 'LI') count++; prevsib = prevsib.previousSibling; } insertNode.setAttribute('start', count); } } else { insertNode = insertNode.childNodes[j]; if(insertNode.tagName.toUpperCase() == 'OL' && (insertNode.start==-1 || insertNode.start==1) && n.nodeType == 1 && n.tagName.toUpperCase() =='LI') { // happens if the tag was created while processing a text node. var prevsib = n.previousSibling; var count=0; while(prevsib) { if(prevsib.nodeType==1 && prevsib.tagName.toUpperCase() == 'LI') count++; prevsib = prevsib.previousSibling; } insertNode.setAttribute('start', count); } } } return insertNode; } function moveNode(n,col1,col2) { var insertNode=createNodeAncestors(n,col1,col2, 'append'); var movedNode = insertNode.appendChild(n.parentNode.removeChild(n)); if(insertNode.id == col2.id && movedNode.nodeType ==1 ) { movedNode.style.paddingTop = "0px"; movedNode.style.marginTop = "0px"; } return movedNode; } function getElementRelativeTop(obj, refObj) { var cur = 0; if(obj.offsetParent) { while(obj.offsetParent) { cur+=obj.offsetTop; obj = obj.offsetParent; } } var cur2 = 0; if(refObj.offsetParent) { while(refObj.offsetParent) { cur2+=refObj.offsetTop; refObj = refObj.offsetParent; } } return cur-cur2; // + document.body.offsetTop; } } // ===================================================================================== // Utility Class Constructor skeleton function CSS3Utility() { // Event Handler utility list this.handlerList = new Array(); } // Public Methods // ============== // querying of a DOM document using CSS selectors (a getElementsByTagName on steroids) // see http://dean.edwards.name/my/cssQuery.js.html /* License: http://creativecommons.org/licenses/by/1.0/ Author: Dean Edwards/2004 Web: http://dean.edwards.name/ */ CSS3Utility.prototype.cssQuery = function() { var version = "1.0.1"; // timestamp: 2004/05/25 // constants var STANDARD_SELECT = /^[^>\+~\s]/; var STREAM = /[\s>\+~:@#\.]|[^\s>\+~:@#\.]+/g; var NAMESPACE = /\|/; var IMPLIED_SELECTOR = /([\s>\+~\,]|^)([\.:#@])/g; var ASTERISK ="$1*$2"; var WHITESPACE = /^\s+|\s*([\+\,>\s;:])\s*|\s+$/g; var TRIM = "$1"; var NODE_ELEMENT = 1; var NODE_TEXT = 3; var NODE_DOCUMENT = 9; // sniff for explorer (cos of one little bug) var isMSIE = /MSIE/.test(navigator.appVersion), isXML; // cache results for faster processing var cssCache = {}; // this is the query function function cssQuery(selector, from) { if (!selector) return []; var useCache = arguments.callee.caching && !from; from = (from) ? (from.constructor == Array) ? from : [from] : [document]; isXML = false;//checkXML(from[0]); // process comma separated selectors var selectors = parseSelector(selector).split(","); var match = []; for (var i in selectors) { // convert the selector to a stream selector = toStream(selectors[i]); // process the stream var j = 0, token, filter, cacheSelector = "", filtered = from; while (j < selector.length) { token = selector[j++]; filter = selector[j++]; cacheSelector += token + filter; // process a token/filter pair filtered = (useCache && cssCache[cacheSelector]) ? cssCache[cacheSelector] : select(filtered, token, filter); if (useCache) cssCache[cacheSelector] = filtered; } match = match.concat(filtered); } // return the filtered selection return match; }; cssQuery.caching = false; cssQuery.reset = function() { cssCache = {}; }; cssQuery.toString = function () { return "function cssQuery() {\n [version " + version + "]\n}"; }; var checkXML = (isMSIE) ? function(node) { if (node.nodeType != NODE_DOCUMENT) node = node.document; return node.mimeType == "XML Document"; } : function(node) { if (node.nodeType == NODE_DOCUMENT) node = node.documentElement; return node.localName != "HTML"; }; function parseSelector(selector) { return selector // trim whitespace .replace(WHITESPACE, TRIM) // encode attribute selectors .replace(attributeSelector.ALL, attributeSelector.ID) // e.g. ".class1" --> "*.class1" .replace(IMPLIED_SELECTOR, ASTERISK); }; // convert css selectors to a stream of tokens and filters // it's not a real stream. it's just an array of strings. function toStream(selector) { if (STANDARD_SELECT.test(selector)) selector = " " + selector; return selector.match(STREAM) || []; }; var pseudoClasses = { // static // CSS1 "link": function(element) { for (var i = 0; i < document.links; i++) { if (document.links[i] == element) return true; } }, "visited": function(element) { // can't do this without jiggery-pokery }, // CSS2 "first-child": function(element) { return !previousElement(element); }, // CSS3 "last-child": function(element) { return !nextElement(element); }, "root": function(element) { var document = element.ownerDocument || element.document; return Boolean(element == document.documentElement); }, "empty": function(element) { for (var i = 0; i < element.childNodes.length; i++) { if (isElement(element.childNodes[i]) || element.childNodes[i].nodeType == NODE_TEXT) return false; } return true; } // add your own... }; var QUOTED = /([\'\"])[^\1]*\1/; function quote(value) {return (QUOTED.test(value)) ? value : "'" + value + "'"}; function unquote(value) {return (QUOTED.test(value)) ? value.slice(1, -1) : value}; var attributeSelectors = []; function attributeSelector(attribute, compare, value) { // properties this.id = attributeSelectors.length; // build the test expression var test = "element."; switch (attribute.toLowerCase()) { case "id": test += "id"; break; case "class": test += "className"; break; default: test += "getAttribute('" + attribute + "')"; } // continue building the test expression switch (compare) { case "=": test += "==" + quote(value); break; case "~=": test = "/(^|\\s)" + unquote(value) + "(\\s|$)/.test(" + test + ")"; break; case "|=": test = "/(^|-)" + unquote(value) + "(-|$)/.test(" + test + ")"; break; } push(attributeSelectors, new Function("element", "return " + test)); }; attributeSelector.prototype.toString = function() { return attributeSelector.PREFIX + this.id; }; // constants attributeSelector.PREFIX = "@"; attributeSelector.ALL = /\[([^~|=\]]+)([~|]?=?)([^\]]+)?\]/g; // class methods attributeSelector.ID = function(match, attribute, compare, value) { return new attributeSelector(attribute, compare, value); }; // select a set of matching elements. // "from" is an array of elements. // "token" is a character representing the type of filter // e.g. ">" means child selector // "filter" represents the tag name, id or class name that is being selected // the function returns an array of matching elements function select(from, token, filter) { //alert("token="+token+",filter="+filter); var namespace = ""; if (NAMESPACE.test(filter)) { filter = filter.split("|"); namespace = filter[0]; filter = filter[1]; } var filtered = [], i; switch (token) { case " ": // descendant for (i in from) { if(typeof from[i]=='function') continue; var subset = getElementsByTagNameNS(from[i], filter, namespace); for (var j = 0; j < subset.length; j++) { if (isElement(subset[j]) && (!namespace || compareNamespace(subset[j], namespace))) push(filtered, subset[j]); } } break; case ">": // child for (i in from) { var subset = from[i].childNodes; for (var j = 0; j < subset.length; j++) if (compareTagName(subset[j], filter, namespace)) push(filtered, subset[j]); } break; case "+": // adjacent (direct) for (i in from) { var adjacent = nextElement(from[i]); if (adjacent && compareTagName(adjacent, filter, namespace)) push(filtered, adjacent); } break; case "~": // adjacent (indirect) for (i in from) { var adjacent = from[i]; while (adjacent = nextElement(adjacent)) { if (adjacent && compareTagName(adjacent, filter, namespace)) push(filtered, adjacent); } } break; case ".": // class filter = new RegExp("(^|\\s)" + filter + "(\\s|$)"); for (i in from) if (filter.test(from[i].className)) push(filtered, from[i]); break; case "#": // id for (i in from) if (from[i].id == filter) push(filtered, from[i]); break; case "@": // attribute selector filter = attributeSelectors[filter]; for (i in from) if (filter(from[i])) push(filtered, from[i]); break; case ":": // pseudo-class (static) filter = pseudoClasses[filter]; for (i in from) if (filter(from[i])) push(filtered, from[i]); break; } return filtered; }; var getElementsByTagNameNS = (isMSIE) ? function(from, tagName) { return (tagName == "*" && from.all) ? from.all : from.getElementsByTagName(tagName); } : function(from, tagName, namespace) { return (namespace) ? from.getElementsByTagNameNS("*", tagName) : from.getElementsByTagName(tagName); }; function compareTagName(element, tagName, namespace) { if (namespace && !compareNamespace(element, namespace)) return false; return (tagName == "*") ? isElement(element) : (isXML) ? (element.tagName == tagName) : (element.tagName == tagName.toUpperCase()); }; var PREFIX = (isMSIE) ? "scopeName" : "prefix"; function compareNamespace(element, namespace) { return element[PREFIX] == namespace; }; // return the previous element to the supplied element // previousSibling is not good enough as it might return a text or comment node function previousElement(element) { while ((element = element.previousSibling) && !isElement(element)) continue; return element; }; // return the next element to the supplied element function nextElement(element) { while ((element = element.nextSibling) && !isElement(element)) continue; return element; }; function isElement(node) { return Boolean(node.nodeType == NODE_ELEMENT && node.tagName != "!"); }; // use a baby push function because IE5.0 doesn't support Array.push function push(array, item) { array[array.length] = item; }; // fix IE5.0 String.replace if ("i".replace(/i/,function(){return""})) { // preserve String.replace var string_replace = String.prototype.replace; // create String.replace for handling functions var function_replace = function(regexp, replacement) { var match, newString = "", string = this; while ((match = regexp.exec(string))) { // five string replacement arguments is sufficent for cssQuery newString += string.slice(0, match.index) + replacement(match[0], match[1], match[2], match[3], match[4]); string = string.slice(match.lastIndex); } return newString + string; }; // replace String.replace String.prototype.replace = function (regexp, replacement) { this.replace = (typeof replacement == "function") ? function_replace : string_replace; return this.replace(regexp, replacement); }; } return cssQuery; }(); // Cross-Browser event handler. CSS3Utility.prototype.XBrowserAddEventHandler = function(target,eventName,handlerName) { if(!target) return; if (target.addEventListener) { target.addEventListener(eventName, function(e){eval(handlerName)(e);}, false); } else if (target.attachEvent) { target.attachEvent("on" + eventName, function(e){eval(handlerName)(e);}); } else { // THIS CODE NOT TESTED var originalHandler = target["on" + eventName]; if (originalHandler) { target["on" + eventName] = function(e){originalHandler(e);eval(handlerName)(e);}; } else { target["on" + eventName] = eval(handlerName); } } // Keep track of added handlers. var l = this.handlerList.length; this.handlerList[l] = new Array(2); this.handlerList[l][0] = target.id; this.handlerList[l][1] = eventName; // see http://weblogs.asp.net/asmith/archive/2003/10/06/30744.aspx // for a complete XBrowserAddEventHandler } // getPseudoCssRules() // Constructor for a pseudo-css rule object // (an unsupported property, thus not present in the DOM rules collection) // Constructor parameters // ---------------------- // the css property name // the stylesheet (as a text stream) // Object properties: // ------------------ // selector (string) // property (string) // value (string) CSS3Utility.prototype.getPseudoCssRules = function(propertyName, serializedStylesheet) { this.cssRules = new Array(); var valuePattern = propertyName.replace("-","\-")+"[\\s]*:[\\s]*([^;}]*)[;}]"; var selectorPattern = "$"; var regx = new RegExp(valuePattern,"g"); var regxMatch = regx.exec(serializedStylesheet); var j=0; while(regxMatch){ var str = serializedStylesheet.substr(0,serializedStylesheet.substr(0,serializedStylesheet.indexOf(regxMatch[0])).lastIndexOf('{')); var selectorText = str.substr(str.lastIndexOf('}')+1).replace(/^\s*|\s*$/g,""); // ignore commented rule !! this.cssRules[j] = new Object(); this.cssRules[j].selectorText = selectorText; this.cssRules[j].property = propertyName; this.cssRules[j].value = regxMatch[1].replace(/(\r?\n)*/g,""); // suppress line breaks j++; regxMatch = regx.exec(serializedStylesheet); } } // Generates a random ID CSS3Utility.prototype.randomId = function () { var rId = ""; for (var i=0; i<6;i++) rId += String.fromCharCode(97 + Math.floor((Math.random()*24))) return rId; } CSS3Utility.prototype.debug = function(text) { var debugOutput = document.getElementById('debugOutput'); // Debug Output if(typeof debugOutput != "undefined" && debugOutput) { //debugOutput.appendChild(document.createElement('hr')); //debugOutput.appendChild(document.createTextNode(text)); debugOutput.innerHTML+= text; } } // Object Instance var css3MC = new CSS3MultiColumn();