2 LowPro.Version = '0.1';
4 // Adapted from DOM Ready extension by Dan Webb
5 // http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
6 // which was based on work by Matthias Miller, Dean Edwards and John Resig
10 // Event.onReady(callbackFunction);
11 Object.extend(Event, {
12 _domReady : function() {
13 if (arguments.callee.done) return;
14 arguments.callee.done = true;
16 if (Event._timer) clearInterval(Event._timer);
18 Event._readyCallbacks.each(function(f) { f() });
19 Event._readyCallbacks = null;
22 onReady : function(f) {
23 if (!this._readyCallbacks) {
24 var domReady = this._domReady;
26 if (domReady.done) return f();
28 if (document.addEventListener)
29 document.addEventListener("DOMContentLoaded", domReady, false);
33 document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
34 document.getElementById("__ie_onload").onreadystatechange = function() {
35 if (this.readyState == "complete") { domReady(); }
39 if (/WebKit/i.test(navigator.userAgent)) {
40 this._timer = setInterval(function() {
41 if (/loaded|complete/.test(document.readyState)) domReady();
45 Event.observe(window, 'load', domReady);
46 Event._readyCallbacks = [];
48 Event._readyCallbacks.push(f);
52 if (!Element.addMethods)
53 Element.addMethods = function(o) { Object.extend(Element.Methods, o) };
55 // Extend Element with observe and stopObserving.
57 observe : function(el, event, callback) {
58 Event.observe(el, event, callback);
60 stopObserving : function(el, event, callback) {
61 Event.stopObserving(el, event, callback);
65 // Replace out existing event observe code with Dean Edwards' addEvent
66 // http://dean.edwards.name/weblog/2005/10/add-event/
67 Object.extend(Event, {
68 observe : function(el, type, func) {
70 if (!func.$$guid) func.$$guid = Event._guid++;
71 if (!el.events) el.events = {};
72 var handlers = el.events[type];
74 handlers = el.events[type] = {};
75 if (el["on" + type]) {
76 handlers[0] = el["on" + type];
79 handlers[func.$$guid] = func;
80 el["on" + type] = Event._handleEvent;
82 if (!Event.observers) Event.observers = [];
83 Event.observers.push([el, name, func, false]);
85 stopObserving : function(el, type, func) {
86 if (el.events && el.events[type]) delete el.events[type][func.$$guid];
88 _handleEvent : function(e) {
89 var returnValue = true;
90 e = e || Event._fixEvent(window.event);
91 var handlers = this.events[e.type], el = $(this);
92 for (var i in handlers) {
93 el.$$handleEvent = handlers[i];
94 if (el.$$handleEvent(e) === false) returnValue = false;
98 _fixEvent : function(e) {
99 e.preventDefault = Event._preventDefault;
100 e.stopPropagation = Event._stopPropagation;
103 _preventDefault : function() { this.returnValue = false },
104 _stopPropagation : function() { this.cancelBubble = true },
108 // Allows you to trigger an event element.
109 Object.extend(Event, {
110 trigger : function(element, event, fakeEvent) {
111 element = $(element);
112 fakeEvent = fakeEvent || { type : event };
113 this.observers.each(function(cache) {
114 if (cache[0] == element && cache[1] == event)
115 cache[2].call(element, fakeEvent);
120 // Based on event:Selectors by Justin Palmer
121 // http://encytemedia.com/event-selectors/
125 // Event.addBehavior({
126 // "selector:event" : function(event) { /* event handler. this refers to the element. */ },
127 // "selector" : function() { /* runs function on dom ready. this refers to the element. */ }
131 // Multiple calls will add to exisiting rules. Event.addBehavior.reassignAfterAjax and
132 // Event.addBehavior.autoTrigger can be adjusted to needs.
133 Event.addBehavior = function(rules) {
134 var ab = this.addBehavior;
135 Object.extend(ab.rules, rules);
137 if (ab.autoTrigger) {
138 this.onReady(ab.load.bind(ab));
141 Ajax.Responders.register({
142 onComplete : function() {
143 if (Event.addBehavior.reassignAfterAjax)
144 setTimeout(function() { ab.load() }, 10);
150 Object.extend(Event.addBehavior, {
151 rules : {}, cache : [],
152 reassignAfterAjax : true,
157 for (var selector in this.rules) {
158 var observer = this.rules[selector];
159 var sels = selector.split(',');
160 sels.each(function(sel) {
161 var parts = sel.split(/:(?=[a-z]+$)/), css = parts[0], event = parts[1];
162 $$(css).each(function(element) {
164 $(element).observe(event, observer);
165 Event.addBehavior.cache.push([element, event, observer]);
167 if (!element.$$assigned || !element.$$assigned.include(observer)) {
168 if (observer.attach) observer.attach(element);
169 else observer.call($(element));
170 element.$$assigned = element.$$assigned || [];
171 element.$$assigned.push(observer);
179 unload : function() {
180 this.cache.each(function(c) {
181 Event.stopObserving.apply(Event, c);
187 Event.observe(window, 'unload', Event.addBehavior.unload.bind(Event.addBehavior));
189 // Behaviors can be bound to elements to provide an object orientated way of controlling elements
190 // and their behavior. Use Behavior.create() to make a new behavior class then use attach() to
191 // glue it to an element. Each element then gets it's own instance of the behavior and any
192 // methods called onxxx are bound to the relevent event.
196 // var MyBehavior = Behavior.create({
197 // onmouseover : function() { this.element.addClassName('bong') }
200 // Event.addBehavior({ 'a.rollover' : MyBehavior });
202 create : function(members) {
203 var behavior = Class.create();
204 behavior.prototype.initialize = Prototype.K;
205 Object.extend(behavior.prototype, members);
206 Object.extend(behavior, Behavior.ClassMethods);
210 attach : function(element) {
211 var bound = new this;
212 bound.element = $(element);
213 this._bindEvents(bound);
216 _bindEvents : function(bound) {
217 for (var member in bound)
218 if (member.match(/^on(.+)/) && typeof bound[member] == 'function')
219 bound.element.observe(RegExp.$1, bound[member].bindAsEventListener(bound));
225 // Original code by Sylvian Zimmer
226 // http://www.sylvainzimmer.com/index.php/archives/2006/06/25/speeding-up-prototypes-selector/
227 // Optimises execution speed of the $$ function. Rewritten for readability by Justin Palmer.
229 // Turn off optimisation with LowPro.optimize$$ = false;
230 LowPro.SelectorLite = Class.create();
231 LowPro.SelectorLite.prototype = {
232 initialize: function(selectors) {
237 for(var i = selectors.length -1; i >= 0; i--) {
238 var params = { tag: '*', id: null, classes: [] };
239 var selector = selectors[i];
240 var needle = selector.length - 1;
243 var id = selector.lastIndexOf("#");
244 var klass = selector.lastIndexOf(".");
245 var cursor = Math.max(id, klass);
247 if(cursor == -1) params.tag = selector.toUpperCase();
248 else if(id == -1 || klass == cursor) params.classes.push(selector.substring(klass + 1))
249 else if(!params.id) params.id = selector.substring(id + 1);
251 selector = selector.substring(0, cursor);
253 this.selectors[i] = params;
258 get: function(root) {
259 this.findElements(root || document, this.index == (this.selectors.length - 1));
263 findElements: function(parent, descendant) {
264 var selector = this.selectors[this.index], results = [], element;
266 element = $(selector.id);
267 if(element && (selector.tag == '*' || element.tagName == selector.tag) &&
268 (element.childOf(parent))) {
272 results = $A(parent.getElementsByTagName(selector.tag));
275 if(selector.classes.length == 1) {
276 results = results.select(function(target) {
277 return $(target).hasClassName(selector.classes[0]);
279 } else if(selector.classes.length > 1) {
280 results = results.select(function(target) {
281 var klasses = $(target).classNames();
282 return selector.classes.all(function(klass) {
283 return klasses.include(klass);
289 this.results = this.results.concat(results);
292 results.each(function(target) {
293 this.findElements(target, this.index == (this.selectors.length - 1));
300 LowPro.optimize$$ = true;
303 if (LowPro.optimize$$ == false || b || a.indexOf("[")>=0)
304 return LowPro.$$old.apply(this, arguments);
305 return new LowPro.SelectorLite(a.split(/\s+/)).get();