4 * Ajatus - Distributed CRM
5 * @requires jQuery v1.2.1
7 * Copyright (c) 2007 Jerry Jalava <jerry.jalava@gmail.com>
8 * Copyright (c) 2007 Nemein Oy <http://nemein.com>
9 * Website: http://ajatus.info
10 * Licensed under the GPL license
11 * http://www.gnu.org/licenses/gpl.html
16 $.ajatus
= $.ajatus
|| {};
23 $.extend($.ajatus
.history
, {
25 $.ajatus
.history
.enabled
= typeof($.ajatus
.history
.handler
) != 'undefined' ? true : false;
27 if ($.ajatus
.history
.enabled
) {
28 $.ajatus
.history
._handler
= new $.ajatus
.history
.handler
;
29 $.ajatus
.history
._handler
.initialize(function(){
30 $.ajatus
.tabs
.set_active_by_hash('#view.frontpage');
31 $.ajatus
.views
.system
.frontpage
.render();
35 add_map: function(hash
, action
) {
36 $.ajatus
.history
._handler
.add_map(hash
, action
);
38 add_dynamic_map: function() {
43 statics
= arguments
[0];
49 action
= arguments
[2];
51 $.ajatus
.history
._handler
.add_dynamic_map(statics
, mods
, action
);
53 update: function(hash
) {
54 $.ajatus
.history
._handler
.update(hash
);
56 check: function(hash
) {
57 if (typeof hash
== 'undefined') {
58 var hash
= $.ajatus
.history
._handler
.get_hash();
60 // $.ajatus.debug('$.ajatus.history.check('+hash+')');
62 if ( !$.browser
.mozilla
63 && $.ajatus
.history
.last_checked
== hash
)
65 //$.ajatus.debug('$.ajatus.history.check skipping hash '+hash);
68 $.ajatus
.history
.last_checked
= hash
;
70 if ($.ajatus
.history
._handler
.executable(hash
)) {
71 $.ajatus
.tabs
.set_active_by_hash(hash
);
72 $.ajatus
.history
._handler
.execute(hash
);
78 navigate: function(count
) {
79 if (typeof count
== 'undefined') {
83 $.ajatus
.history
._handler
.navigate(count
);
88 * Base idea is taken from $.ajaxHistory plugin by Klaus Hartl
89 * Difference in this is that we evaluate predefined actions
90 * that are mapped against hashes.
92 $.ajatus
.history
.handler = function(){
95 var dyn_mappings
= [];
97 var RESET_EVENT
= 'historyReset';
99 var _currentHash
= location
.hash
;
100 var _intervalId
= null;
103 this.update = function(){}; // empty function body for graceful degradation
105 this.add_map = function(hash
, action
) {
106 mappings
[hash
] = action
;
109 this.add_dynamic_map = function(statics
, mods
, action
) {
111 $.each(statics
, function(i
,s
){
120 dyn_mappings
.push(dyn_map
);
123 this.is_dyn_mapping = function(hash
) {
124 var ch
= hash
.replace('#','');
125 var hash_parts
= ch
.split(/\./);
129 $.each(dyn_mappings
, function(i
,dm
){
132 $.each(dm
.statics
, function(k
,n
){
133 if (hash_parts
[k
] == n
) {
139 $.each(hash_parts
, function(hk
,hp
){
140 if ( hk
> matched_key
157 this.executable = function(hash
){
158 if (mappings
[hash
]) {
161 var dm_data
= this.is_dyn_mapping(hash
);
162 if (dm_data
!== false) {
169 this.execute = function(hash
){
170 //$.ajatus.debug('$.ajatus.extension.history.execute('+hash+')');
172 if (mappings
[hash
]) {
173 eval(mappings
[hash
]);
175 //$.ajatus.debug('$.ajatus.extension.history.execute evaled from mappings: '+mappings[hash]);
179 var dm_data
= this.is_dyn_mapping(hash
);
180 if (dm_data
!== false) {
181 //$.ajatus.debug('$.ajatus.extension.history.execute hash is dynamic mapping. Evaling: '+dyn_mappings[dm_data.id].action);
183 var func
= eval(dyn_mappings
[dm_data
.id
].action
);
184 func
.apply(func
, dm_data
.args
);
192 this.get_hash = function(){
195 if ($.browser
.safari
) {
196 if (window
.document
.URL
.indexOf('#') >= 0) {
197 hash
= '#'+window
.document
.URL
.split('#')[1];
200 hash
= location
.hash
;
206 // create custom event for state reset
207 var _defaultReset = function() {
209 $(window
.document
).bind(RESET_EVENT
, _defaultReset
);
211 if ($.browser
.safari
) {
213 var _backStack
, _forwardStack
, _addHistory
; // for Safari
215 // establish back/forward stacks
218 _backStack
.length
= history
.length
;
221 var isFirst
= false, initialized
= false;
222 _addHistory = function(hash
) {
223 _backStack
.push(hash
);
224 _forwardStack
.length
= 0; // clear forwardStack (true click occured)
228 this.update = function(hash
) {
230 location
.hash
= hash
;
231 _addHistory(_currentHash
);
234 this.navigate = function(count
) {
236 var idx
= (_backStack
.length
+ count
) - 1;
237 var newHash
= _backStack
[idx
];
239 var idx
= (_forwardStack
.length
- count
) - 1;
240 var newHash
= _forwardStack
[idx
];
243 if (typeof newHash
!= 'undefined') {
244 $.ajatus
.history
.update(newHash
);
248 _observeHistory = function() {
249 var historyDelta
= history
.length
- _backStack
.length
;
250 if (historyDelta
) { // back or forward button has been pushed
252 if (historyDelta
< 0) { // back button has been pushed
253 // move items to forward stack
254 for (var i
= 0; i
< Math
.abs(historyDelta
); i
++) _forwardStack
.unshift(_backStack
.pop());
255 } else { // forward button has been pushed
256 // move items to back stack
257 for (var i
= 0; i
< historyDelta
; i
++) _backStack
.push(_forwardStack
.shift());
259 var cachedHash
= _backStack
[_backStack
.length
- 1];
260 _currentHash
= location
.hash
;
262 $.ajatus
.history
.check(_currentHash
);
263 } else if (typeof(_backStack
[_backStack
.length
- 1]) == 'undefined' && !isFirst
) {
264 if (location
.hash
== '') {
265 $(window
.document
).trigger(RESET_EVENT
);
273 this.update = function(hash
) {
274 location
.hash
= hash
;
278 _observeHistory = function() {
280 if (_currentHash
!= location
.hash
) {
281 _currentHash
= location
.hash
;
282 $.ajatus
.history
.check(_currentHash
);
284 } else if (_currentHash
) {
286 $(window
.document
).trigger(RESET_EVENT
);
290 this.navigate = function(count
) {
291 window
.history
.go(count
);
295 this.initialize = function(callback
) {
296 // custom callback to reset app state (no hash in url)
297 if (typeof callback
== 'function') {
298 $(window
.document
).unbind(RESET_EVENT
, _defaultReset
).bind(RESET_EVENT
, callback
);
300 // look for hash in current URL (not Safari) and execute predefined action if one is found
301 if (location
.hash
&& typeof _addHistory
== 'undefined') {
302 $.ajatus
.history
.check(location
.hash
);
305 if (_observeHistory
&& _intervalId
== null) {
306 _intervalId
= setInterval(_observeHistory
, 200); // Safari needs at least 200 ms