summaryrefslogtreecommitdiff
path: root/itjs/state.js
blob: 9521093a6dbf19451c58feb65f4d5ff766f11a9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
 * Generic state object (singleton), for supporting Ajax browser history
 *
 * $Id$
 *
 */
var it_state =
{
it_iframe: null,
it_history_field: null,
it_store_handlers: [],
it_restore_handlers: [],

/**
 * Register a handler that gets called before creating a history entry
 * @param p.object Object that contains handler method
 * @param p.method Method of p.object to call
 */
register_store_handler: function(p)
{
	this.it_store_handlers[this.it_store_handlers.length] = p;
},


/**
 * Register a handler that gets called after restoring a history entry
 * @param p.object Object that contains handler method
 * @param p.method Method of p.object to call
 * @param p.initial optional flag: if true, handler is called with initial empty state
 */
register_restore_handler: function(p)
{
	this.it_restore_handlers[this.it_restore_handlers.length] = p;

	// If we already have state data, call registered handler immediately. Yup this _is_ needed!
	if (this.it_history_field && this.it_history_field.value)
		p.object[p.method]();
},


/**
 * Create a new history entry, saving all values of it_state (asynchronously)
 * Users must call this without parameter!
 */
new_history_entry: function(p)
{
	// ED('it_state::new_history_entry()');

	if (!this.it_iframe && !(this.it_iframe = document.getElementById('it_state')))
		ED('it_state::new_history_entry(): it_state object not found!');

	this.it_iframe.src = "/itjs/state.html?t="+it_now();
	this.it_history_field = null;
},


/**
 * Restore state from history, called from iframe's onload handler but in main window's context
 */
restore_history: function()
{
	if (!this.it_iframe && !(this.it_iframe = document.getElementById('it_state')))
		ED('it_state::restore_history(): it_state object not found!');
	
	var idoc = it_get_iframe_document(this.it_iframe);
	this.it_history_field = idoc ? idoc.getElementById('state') : {};	// Work-around IE5 not returning iframe document

	if (this.it_history_field.value)
	{
		var res = eval('({' + this.it_history_field.value + '})');
		// ED('it_state::restore_history(): restoring these settings:', res);
		for (var key in res)
			this[key] = res[key];
	}

	for (var i in this.it_restore_handlers)
	{
		if (this.it_history_field.value || (this.it_restore_handlers[i].initial && (!idoc || !it_get_iframe_document(this.it_iframe).location.href.match(/t=/))))
			this.it_restore_handlers[i].object[this.it_restore_handlers[i].method]();
	}
},


/**
 * Call all store handlers and store state in it_history_field
 */
store_state: function()
{
	if (!this.it_iframe && !(this.it_iframe = document.getElementById('it_state')))
		ED('it_state::store_state(): it_state object not found!');

	var idoc = it_get_iframe_document(this.it_iframe);
	this.it_history_field = idoc ? idoc.getElementById('state') : {};	// Work-around IE5 not returning iframe document

	for (var i in this.it_store_handlers)
		this.it_store_handlers[i].object[this.it_store_handlers[i].method]();

	var ser = [];
	for (var key in this)
	{
		var value = this[key], type = typeof(value);
		if (!key.match(/^it_/) && type.match(/boolean|number|string/))
			ser[ser.length] = key + ':' + ((type == 'string') ? "'" + value.replace(/([\\'])/g, '\\\1') + "'" : value);
	}

	// ED('it_state::store_state()', ser);
	this.it_history_field.value = ser.join(',');
}/* NO COMMA */
}

function it_state_restore_history()
{
	it_state.restore_history();
}