mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-17 15:50:13 +01:00
308 lines
9.3 KiB
JavaScript
308 lines
9.3 KiB
JavaScript
|
|
LowPro = {};
|
||
|
|
LowPro.Version = '0.1';
|
||
|
|
|
||
|
|
// Adapted from DOM Ready extension by Dan Webb
|
||
|
|
// http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
|
||
|
|
// which was based on work by Matthias Miller, Dean Edwards and John Resig
|
||
|
|
//
|
||
|
|
// Usage:
|
||
|
|
//
|
||
|
|
// Event.onReady(callbackFunction);
|
||
|
|
Object.extend(Event, {
|
||
|
|
_domReady : function() {
|
||
|
|
if (arguments.callee.done) return;
|
||
|
|
arguments.callee.done = true;
|
||
|
|
|
||
|
|
if (Event._timer) clearInterval(Event._timer);
|
||
|
|
|
||
|
|
Event._readyCallbacks.each(function(f) { f() });
|
||
|
|
Event._readyCallbacks = null;
|
||
|
|
|
||
|
|
},
|
||
|
|
onReady : function(f) {
|
||
|
|
if (!this._readyCallbacks) {
|
||
|
|
var domReady = this._domReady;
|
||
|
|
|
||
|
|
if (domReady.done) return f();
|
||
|
|
|
||
|
|
if (document.addEventListener)
|
||
|
|
document.addEventListener("DOMContentLoaded", domReady, false);
|
||
|
|
|
||
|
|
/*@cc_on @*/
|
||
|
|
/*@if (@_win32)
|
||
|
|
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
|
||
|
|
document.getElementById("__ie_onload").onreadystatechange = function() {
|
||
|
|
if (this.readyState == "complete") { domReady(); }
|
||
|
|
};
|
||
|
|
/*@end @*/
|
||
|
|
|
||
|
|
if (/WebKit/i.test(navigator.userAgent)) {
|
||
|
|
this._timer = setInterval(function() {
|
||
|
|
if (/loaded|complete/.test(document.readyState)) domReady();
|
||
|
|
}, 10);
|
||
|
|
}
|
||
|
|
|
||
|
|
Event.observe(window, 'load', domReady);
|
||
|
|
Event._readyCallbacks = [];
|
||
|
|
}
|
||
|
|
Event._readyCallbacks.push(f);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!Element.addMethods)
|
||
|
|
Element.addMethods = function(o) { Object.extend(Element.Methods, o) };
|
||
|
|
|
||
|
|
// Extend Element with observe and stopObserving.
|
||
|
|
Element.addMethods({
|
||
|
|
observe : function(el, event, callback) {
|
||
|
|
Event.observe(el, event, callback);
|
||
|
|
},
|
||
|
|
stopObserving : function(el, event, callback) {
|
||
|
|
Event.stopObserving(el, event, callback);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Replace out existing event observe code with Dean Edwards' addEvent
|
||
|
|
// http://dean.edwards.name/weblog/2005/10/add-event/
|
||
|
|
Object.extend(Event, {
|
||
|
|
observe : function(el, type, func) {
|
||
|
|
el = $(el);
|
||
|
|
if (!func.$$guid) func.$$guid = Event._guid++;
|
||
|
|
if (!el.events) el.events = {};
|
||
|
|
var handlers = el.events[type];
|
||
|
|
if (!handlers) {
|
||
|
|
handlers = el.events[type] = {};
|
||
|
|
if (el["on" + type]) {
|
||
|
|
handlers[0] = el["on" + type];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
handlers[func.$$guid] = func;
|
||
|
|
el["on" + type] = Event._handleEvent;
|
||
|
|
|
||
|
|
if (!Event.observers) Event.observers = [];
|
||
|
|
Event.observers.push([el, name, func, false]);
|
||
|
|
},
|
||
|
|
stopObserving : function(el, type, func) {
|
||
|
|
if (el.events && el.events[type]) delete el.events[type][func.$$guid];
|
||
|
|
},
|
||
|
|
_handleEvent : function(e) {
|
||
|
|
var returnValue = true;
|
||
|
|
e = e || Event._fixEvent(window.event);
|
||
|
|
var handlers = this.events[e.type], el = $(this);
|
||
|
|
for (var i in handlers) {
|
||
|
|
el.$$handleEvent = handlers[i];
|
||
|
|
if (el.$$handleEvent(e) === false) returnValue = false;
|
||
|
|
}
|
||
|
|
return returnValue;
|
||
|
|
},
|
||
|
|
_fixEvent : function(e) {
|
||
|
|
e.preventDefault = Event._preventDefault;
|
||
|
|
e.stopPropagation = Event._stopPropagation;
|
||
|
|
return e;
|
||
|
|
},
|
||
|
|
_preventDefault : function() { this.returnValue = false },
|
||
|
|
_stopPropagation : function() { this.cancelBubble = true },
|
||
|
|
_guid : 1
|
||
|
|
});
|
||
|
|
|
||
|
|
// Allows you to trigger an event element.
|
||
|
|
Object.extend(Event, {
|
||
|
|
trigger : function(element, event, fakeEvent) {
|
||
|
|
element = $(element);
|
||
|
|
fakeEvent = fakeEvent || { type : event };
|
||
|
|
this.observers.each(function(cache) {
|
||
|
|
if (cache[0] == element && cache[1] == event)
|
||
|
|
cache[2].call(element, fakeEvent);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Based on event:Selectors by Justin Palmer
|
||
|
|
// http://encytemedia.com/event-selectors/
|
||
|
|
//
|
||
|
|
// Usage:
|
||
|
|
//
|
||
|
|
// Event.addBehavior({
|
||
|
|
// "selector:event" : function(event) { /* event handler. this refers to the element. */ },
|
||
|
|
// "selector" : function() { /* runs function on dom ready. this refers to the element. */ }
|
||
|
|
// ...
|
||
|
|
// });
|
||
|
|
//
|
||
|
|
// Multiple calls will add to exisiting rules. Event.addBehavior.reassignAfterAjax and
|
||
|
|
// Event.addBehavior.autoTrigger can be adjusted to needs.
|
||
|
|
Event.addBehavior = function(rules) {
|
||
|
|
var ab = this.addBehavior;
|
||
|
|
Object.extend(ab.rules, rules);
|
||
|
|
|
||
|
|
if (ab.autoTrigger) {
|
||
|
|
this.onReady(ab.load.bind(ab));
|
||
|
|
}
|
||
|
|
|
||
|
|
Ajax.Responders.register({
|
||
|
|
onComplete : function() {
|
||
|
|
if (Event.addBehavior.reassignAfterAjax)
|
||
|
|
setTimeout(function() { ab.load() }, 10);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
Object.extend(Event.addBehavior, {
|
||
|
|
rules : {}, cache : [],
|
||
|
|
reassignAfterAjax : true,
|
||
|
|
autoTrigger : true,
|
||
|
|
|
||
|
|
load : function() {
|
||
|
|
this.unload();
|
||
|
|
for (var selector in this.rules) {
|
||
|
|
var observer = this.rules[selector];
|
||
|
|
var sels = selector.split(',');
|
||
|
|
sels.each(function(sel) {
|
||
|
|
var parts = sel.split(/:(?=[a-z]+$)/), css = parts[0], event = parts[1];
|
||
|
|
$$(css).each(function(element) {
|
||
|
|
if (event) {
|
||
|
|
$(element).observe(event, observer);
|
||
|
|
Event.addBehavior.cache.push([element, event, observer]);
|
||
|
|
} else {
|
||
|
|
if (!element.$$assigned || !element.$$assigned.include(observer)) {
|
||
|
|
if (observer.attach) observer.attach(element);
|
||
|
|
else observer.call($(element));
|
||
|
|
element.$$assigned = element.$$assigned || [];
|
||
|
|
element.$$assigned.push(observer);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
unload : function() {
|
||
|
|
this.cache.each(function(c) {
|
||
|
|
Event.stopObserving.apply(Event, c);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
|
||
|
|
Event.observe(window, 'unload', Event.addBehavior.unload.bind(Event.addBehavior));
|
||
|
|
|
||
|
|
// Behaviors can be bound to elements to provide an object orientated way of controlling elements
|
||
|
|
// and their behavior. Use Behavior.create() to make a new behavior class then use attach() to
|
||
|
|
// glue it to an element. Each element then gets it's own instance of the behavior and any
|
||
|
|
// methods called onxxx are bound to the relevent event.
|
||
|
|
//
|
||
|
|
// Usage:
|
||
|
|
//
|
||
|
|
// var MyBehavior = Behavior.create({
|
||
|
|
// onmouseover : function() { this.element.addClassName('bong') }
|
||
|
|
// });
|
||
|
|
|
||
|
|
// Event.addBehavior({ 'a.rollover' : MyBehavior });
|
||
|
|
Behavior = {
|
||
|
|
create : function(members) {
|
||
|
|
var behavior = Class.create();
|
||
|
|
behavior.prototype.initialize = Prototype.K;
|
||
|
|
Object.extend(behavior.prototype, members);
|
||
|
|
Object.extend(behavior, Behavior.ClassMethods);
|
||
|
|
return behavior;
|
||
|
|
},
|
||
|
|
ClassMethods : {
|
||
|
|
attach : function(element) {
|
||
|
|
var bound = new this;
|
||
|
|
bound.element = $(element);
|
||
|
|
this._bindEvents(bound);
|
||
|
|
return bound;
|
||
|
|
},
|
||
|
|
_bindEvents : function(bound) {
|
||
|
|
for (var member in bound)
|
||
|
|
if (member.match(/^on(.+)/) && typeof bound[member] == 'function')
|
||
|
|
bound.element.observe(RegExp.$1, bound[member].bindAsEventListener(bound));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
// Original code by Sylvian Zimmer
|
||
|
|
// http://www.sylvainzimmer.com/index.php/archives/2006/06/25/speeding-up-prototypes-selector/
|
||
|
|
// Optimises execution speed of the $$ function. Rewritten for readability by Justin Palmer.
|
||
|
|
//
|
||
|
|
// Turn off optimisation with LowPro.optimize$$ = false;
|
||
|
|
LowPro.SelectorLite = Class.create();
|
||
|
|
LowPro.SelectorLite.prototype = {
|
||
|
|
initialize: function(selectors) {
|
||
|
|
this.results = [];
|
||
|
|
this.selectors = [];
|
||
|
|
this.index = 0;
|
||
|
|
|
||
|
|
for(var i = selectors.length -1; i >= 0; i--) {
|
||
|
|
var params = { tag: '*', id: null, classes: [] };
|
||
|
|
var selector = selectors[i];
|
||
|
|
var needle = selector.length - 1;
|
||
|
|
|
||
|
|
do {
|
||
|
|
var id = selector.lastIndexOf("#");
|
||
|
|
var klass = selector.lastIndexOf(".");
|
||
|
|
var cursor = Math.max(id, klass);
|
||
|
|
|
||
|
|
if(cursor == -1) params.tag = selector.toUpperCase();
|
||
|
|
else if(id == -1 || klass == cursor) params.classes.push(selector.substring(klass + 1))
|
||
|
|
else if(!params.id) params.id = selector.substring(id + 1);
|
||
|
|
|
||
|
|
selector = selector.substring(0, cursor);
|
||
|
|
} while(cursor > 0);
|
||
|
|
this.selectors[i] = params;
|
||
|
|
}
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
get: function(root) {
|
||
|
|
this.findElements(root || document, this.index == (this.selectors.length - 1));
|
||
|
|
return this.results;
|
||
|
|
},
|
||
|
|
|
||
|
|
findElements: function(parent, descendant) {
|
||
|
|
var selector = this.selectors[this.index], results = [], element;
|
||
|
|
if(selector.id) {
|
||
|
|
element = $(selector.id);
|
||
|
|
if(element && (selector.tag == '*' || element.tagName == selector.tag) &&
|
||
|
|
(element.childOf(parent))) {
|
||
|
|
results = [element];
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
results = $A(parent.getElementsByTagName(selector.tag));
|
||
|
|
}
|
||
|
|
|
||
|
|
if(selector.classes.length == 1) {
|
||
|
|
results = results.select(function(target) {
|
||
|
|
return $(target).hasClassName(selector.classes[0]);
|
||
|
|
});
|
||
|
|
} else if(selector.classes.length > 1) {
|
||
|
|
results = results.select(function(target) {
|
||
|
|
var klasses = $(target).classNames();
|
||
|
|
return selector.classes.all(function(klass) {
|
||
|
|
return klasses.include(klass);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if(descendant) {
|
||
|
|
this.results = this.results.concat(results);
|
||
|
|
} else {
|
||
|
|
++this.index;
|
||
|
|
results.each(function(target) {
|
||
|
|
this.findElements(target, this.index == (this.selectors.length - 1));
|
||
|
|
}.bind(this));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
LowPro.$$old=$$;
|
||
|
|
LowPro.optimize$$ = true;
|
||
|
|
|
||
|
|
function $$(a,b) {
|
||
|
|
if (LowPro.optimize$$ == false || b || a.indexOf("[")>=0)
|
||
|
|
return LowPro.$$old.apply(this, arguments);
|
||
|
|
return new LowPro.SelectorLite(a.split(/\s+/)).get();
|
||
|
|
}
|
||
|
|
|