Created
December 16, 2009 15:18
-
-
Save subtleGradient/257903 to your computer and use it in GitHub Desktop.
Harald Kirschner's (http://digitarald.de/) MooTools History (replaces HistoryManager)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
curl -s http://digitarald.de/playground/history/History.js |ruby -e 'print STDIN.read.gsub(/\r/,"")' > History.js | |
curl -s http://digitarald.de/playground/history/History.Routing.js |ruby -e 'print STDIN.read.gsub(/\r/,"")' > History.Routing.js |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* History | |
* | |
* @version 1.0 | |
* | |
* @license MIT License | |
* @author Harald Kirschner <mail [at] digitarald.de> | |
* @copyright 2008 Author | |
*/ | |
var History = $extend(history, { | |
implement: function(obj) { | |
return $extend(this, obj); | |
} | |
}); | |
History.implement(new Events($empty)); | |
History.implement({ | |
state: null, | |
start: function() { | |
if (this.started) return this; | |
this.state = this.getHash(); | |
if (Browser.Engine.trident) { | |
var iframe = new Element('iframe', { | |
'src': "javascript:'<html></html>'", | |
'styles': { | |
'position': 'absolute', | |
'top': '-1000px' | |
} | |
}).inject(document.body).contentWindow; | |
var writeState = function(state) { | |
iframe.document.write('<html><body onload="top.History.$listener(\'', encodeURIComponent(state) ,'\');">Moo!</body></html>'); | |
iframe.document.close(); | |
}; | |
$extend(this, { | |
'$listener': function(state) { | |
state = decodeURIComponent(state); | |
if (this.state != state) this.setHash(state).changeState(state); | |
}.bind(this), | |
'setState': function(state, force) { | |
if (this.state != state || force) { | |
if (!force) this.setHash(state).changeState(state, true); | |
writeState(state); | |
} | |
return this; | |
}, | |
'trace': function() { | |
var state = this.getHash(); | |
if (state != this.state) writeState(state); | |
} | |
}); | |
var check = (function() { | |
if (iframe.document && iframe.document.body) { | |
check = $clear(check); | |
if (!iframe.document.body.innerHTML) this.setState(this.state); | |
} | |
}).periodical(50, this); | |
} else { | |
if (Browser.Engine.presto915) { | |
new Element('img', { | |
'src': "javascript:location.href='javascript:History.trace();';", | |
'styles': { | |
'position': 'absolute', | |
'top': '-1000px' | |
} | |
}).inject(document.body); | |
} | |
} | |
this.trace.periodical(150, this); | |
this.started = true; | |
return this; | |
}, | |
changeState: function(state, manual) { | |
var stateOld = this.state; | |
this.state = state; | |
this.fireEvent('changed', [state, stateOld, manual]); | |
}, | |
trace: function() { | |
var state = this.getHash(); | |
if (state != this.state) this.changeState(state); | |
}, | |
getHash: function() { | |
var href = location.href, pos = href.indexOf('#') + 1; | |
return (pos) ? href.substr(pos) : ''; | |
}, | |
setHash: function(state) { | |
location.hash = '#' + state; | |
return this; | |
}, | |
setState: function(state) { | |
if (this.state !== state) this.setHash(state).changeState(state, true); | |
return this; | |
}, | |
getState: function() { | |
return this.state; | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* History.Routing | |
* | |
* @version 2.0 | |
* | |
* @license MIT License | |
* @author Harald Kirschner <mail [at] digitarald.de> | |
* @copyright 2008 Author | |
*/ | |
History.implement(new Options()); | |
History.implement({ | |
options: { | |
separator: ';' | |
}, | |
routes: [], | |
register: function(route) { | |
if (this.routes.push(route) == 1) this.addEvent('changed', this.match); | |
}, | |
unregister: function(route) { | |
this.routes.remove(route); | |
}, | |
match: function(state, previous, manual) { | |
if (!manual) this.routes.each(Function.methodize('match', this.state)); | |
}, | |
generate: function() { | |
return this.routes.map(Function.methodize('generate')).clean().join(this.options.separator); | |
}, | |
update: function() { | |
return this.setState(this.generate()); | |
} | |
}); | |
History.Route = new Class({ | |
Implements: [Events, Options], | |
/** | |
* pattern: Regular expression that matches the string updated from onGenerate | |
* defaults: Default values array, initially empty. | |
* flags: When regexp is a String, this is the second argument for new RegExp. | |
* skipDefaults: default true; generate is not called when current values are similar to the default values. | |
* generate: Should return the string for the state string, values are first argument | |
* onMatch: Will be called when the regexp matches, with the new values as argument. | |
*/ | |
options: { | |
skipDefaults: true, | |
defaults: [], | |
pattern: null, | |
flags: '', | |
generate: function(values) { | |
return values[0]; | |
}, | |
onMatch: $empty | |
}, | |
initialize: function(options){ | |
this.setOptions(options); | |
this.pattern = this.options.pattern || '(.*)'; | |
if ($type(this.pattern) == 'string') this.pattern = new RegExp(this.pattern, this.options.flags); | |
this.values = this.defaults = this.options.defaults.slice(); | |
History.register(this); | |
return this; | |
}, | |
setValues: function(values) { | |
if (this.values.toString() == values.toString()) return this; | |
this.values = values; | |
History.update(); | |
return this; | |
}, | |
setValue: function(index, value) { | |
if (this.values[index] == value) return this; | |
this.values[index] = value; | |
History.update(); | |
return this; | |
}, | |
build: function(values) { | |
var tmp = this.values.slice(); | |
this.values = values; | |
var state = History.generate(); | |
this.values = tmp; | |
return state; | |
}, | |
destroy: function() { | |
History.unregister(this); | |
}, | |
generate: function() { | |
if (this.options.skipDefaultMatch && (String(this.values) == String(this.defaults))) return null; | |
return this.options.generate.call(this, this.values); | |
}, | |
match: function(state) { | |
var bits = state.match(this.pattern); | |
var defaults = this.defaults; | |
if (bits) { | |
bits.splice(0, 1); | |
for (var i = 0, j = bits.length; i < j; i++) bits[i] = $pick(bits[i], defaults[i] || null); | |
if (String(bits) != String(defaults)) this.values = bits; | |
} else { | |
this.values = this.defaults.slice(); | |
} | |
this.fireEvent('onMatch', [this.values, this.defaults]); | |
} | |
}); | |
Function.methodize = function(name) { | |
var args = Array.slice(arguments, 1); | |
return function(obj) { | |
return obj[name].apply(obj, args); | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment