1/* 2 Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work 3 of Simon Willison (see comments by Simon below). 4 5 Description: 6 7 Uses css selectors to apply javascript behaviours to enable 8 unobtrusive javascript in html documents. 9 10 Usage: 11 12 var myrules = { 13 'b.someclass' : function(element){ 14 element.onclick = function(){ 15 alert(this.innerHTML); 16 } 17 }, 18 '#someid u' : function(element){ 19 element.onmouseover = function(){ 20 this.innerHTML = "BLAH!"; 21 } 22 } 23 }; 24 25 Behaviour.register(myrules); 26 27 // Call Behaviour.apply() to re-apply the rules (if you 28 // update the dom, etc). 29 30 License: 31 32 This file is entirely BSD licensed. 33 34 More information: 35 36 http://ripcord.co.nz/behaviour/ 37 38*/ 39 40var Behaviour = { 41 list : new Array, 42 43 register : function(sheet){ 44 Behaviour.list.push(sheet); 45 }, 46 47 start : function(){ 48 Behaviour.addLoadEvent(function(){ 49 Behaviour.apply(); 50 }); 51 }, 52 53 apply : function(){ 54 for (h=0;sheet=Behaviour.list[h];h++){ 55 for (selector in sheet){ 56 list = document.getElementsBySelector(selector); 57 58 if (!list){ 59 continue; 60 } 61 62 for (i=0;element=list[i];i++){ 63 sheet[selector](element); 64 } 65 } 66 } 67 }, 68 69 addLoadEvent : function(func){ 70 var oldonload = window.onload; 71 72 if (typeof window.onload != 'function') { 73 window.onload = func; 74 } else { 75 window.onload = function() { 76 77 try{ 78 if(typeof oldonload == 'function')oldonload(); 79 } catch ( e ) {;} finally {;} 80 try{ 81 if(typeof func == 'function')func(); 82 } catch ( e ) {;} finally {;} 83 } 84 } 85 } 86} 87 88Behaviour.start(); 89 90/* 91 The following code is Copyright (C) Simon Willison 2004. 92 93 document.getElementsBySelector(selector) 94 - returns an array of element objects from the current document 95 matching the CSS selector. Selectors can contain element names, 96 class names and ids and can be nested. For example: 97 98 elements = document.getElementsBySelect('div#main p a.external') 99 100 Will return an array of all 'a' elements with 'external' in their 101 class attribute that are contained inside 'p' elements that are 102 contained inside the 'div' element which has id="main" 103 104 New in version 0.4: Support for CSS2 and CSS3 attribute selectors: 105 See http://www.w3.org/TR/css3-selectors/#attribute-selectors 106 107 Version 0.4 - Simon Willison, March 25th 2003 108 -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows 109 -- Opera 7 fails 110*/ 111 112function getAllChildren(e) { 113 // Returns all children of element. Workaround required for IE5/Windows. Ugh. 114 return e.all ? e.all : e.getElementsByTagName('*'); 115} 116 117document.getElementsBySelector = function(selector) { 118 // Attempt to fail gracefully in lesser browsers 119 if (!document.getElementsByTagName) { 120 return new Array(); 121 } 122 // Split selector in to tokens 123 var tokens = selector.split(' '); 124 var currentContext = new Array(document); 125 for (var i = 0; i < tokens.length; i++) { 126 token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');; 127 if (token.indexOf('#') > -1) { 128 // Token is an ID selector 129 var bits = token.split('#'); 130 var tagName = bits[0]; 131 var id = bits[1]; 132 var element = document.getElementById(id); 133 if (tagName && element.nodeName.toLowerCase() != tagName) { 134 // tag with that ID not found, return false 135 return new Array(); 136 } 137 // Set currentContext to contain just this element 138 currentContext = new Array(element); 139 continue; // Skip to next token 140 } 141 if (token.indexOf('.') > -1) { 142 // Token contains a class selector 143 var bits = token.split('.'); 144 var tagName = bits[0]; 145 var className = bits[1]; 146 if (!tagName) { 147 tagName = '*'; 148 } 149 // Get elements matching tag, filter them for class selector 150 var found = new Array; 151 var foundCount = 0; 152 for (var h = 0; h < currentContext.length; h++) { 153 var elements; 154 if (tagName == '*') { 155 elements = getAllChildren(currentContext[h]); 156 } else { 157 elements = currentContext[h].getElementsByTagName(tagName); 158 } 159 for (var j = 0; j < elements.length; j++) { 160 found[foundCount++] = elements[j]; 161 } 162 } 163 currentContext = new Array; 164 var currentContextIndex = 0; 165 for (var k = 0; k < found.length; k++) { 166 if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) { 167 currentContext[currentContextIndex++] = found[k]; 168 } 169 } 170 continue; // Skip to next token 171 } 172 // Code to deal with attribute selectors 173 if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) { 174 var tagName = RegExp.$1; 175 var attrName = RegExp.$2; 176 var attrOperator = RegExp.$3; 177 var attrValue = RegExp.$4; 178 if (!tagName) { 179 tagName = '*'; 180 } 181 // Grab all of the tagName elements within current context 182 var found = new Array; 183 var foundCount = 0; 184 for (var h = 0; h < currentContext.length; h++) { 185 var elements; 186 if (tagName == '*') { 187 elements = getAllChildren(currentContext[h]); 188 } else { 189 elements = currentContext[h].getElementsByTagName(tagName); 190 } 191 for (var j = 0; j < elements.length; j++) { 192 found[foundCount++] = elements[j]; 193 } 194 } 195 currentContext = new Array; 196 var currentContextIndex = 0; 197 var checkFunction; // This function will be used to filter the elements 198 switch (attrOperator) { 199 case '=': // Equality 200 checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); }; 201 break; 202 case '~': // Match one of space seperated words 203 checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); }; 204 break; 205 case '|': // Match start with value followed by optional hyphen 206 checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); }; 207 break; 208 case '^': // Match starts with value 209 checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); }; 210 break; 211 case '$': // Match ends with value - fails with "Warning" in Opera 7 212 checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); }; 213 break; 214 case '*': // Match ends with value 215 checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); }; 216 break; 217 default : 218 // Just test for existence of attribute 219 checkFunction = function(e) { return e.getAttribute(attrName); }; 220 } 221 currentContext = new Array; 222 var currentContextIndex = 0; 223 for (var k = 0; k < found.length; k++) { 224 if (checkFunction(found[k])) { 225 currentContext[currentContextIndex++] = found[k]; 226 } 227 } 228 // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue); 229 continue; // Skip to next token 230 } 231 232 if (!currentContext[0]){ 233 return; 234 } 235 236 // If we get here, token is JUST an element (not a class or ID selector) 237 tagName = token; 238 var found = new Array; 239 var foundCount = 0; 240 for (var h = 0; h < currentContext.length; h++) { 241 var elements = currentContext[h].getElementsByTagName(tagName); 242 for (var j = 0; j < elements.length; j++) { 243 found[foundCount++] = elements[j]; 244 } 245 } 246 currentContext = found; 247 } 248 return currentContext; 249} 250
251/* That revolting regular expression explained 252/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/ 253 \---/ \---/\-------------/ \-------/ 254 | | | | 255 | | | The value 256 | | ~,|,^,$,* or = 257 | Attribute 258 Tag 259*/
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.