File: mod_wsf_menu.spl

package info (click to toggle)
spl 1.0~pre6-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 2,352 kB
  • ctags: 2,070
  • sloc: ansic: 16,614; yacc: 3,182; sh: 299; makefile: 165; xml: 156
file content (217 lines) | stat: -rw-r--r-- 6,498 bytes parent folder | download | duplicates (5)
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
 *  SPL - The SPL Programming Language
 *  Copyright (C) 2004, 2005  Clifford Wolf <clifford@clifford.at>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  mod_wsf_menu.spl: WSF Menu Component
 */


/**
 * A module which implements a WSF Component for DHTML menus.
 */

load "wsf";

/**
 * This WSF Component adds a DHTML menu to the application window. It should
 * be the first child of the root component and the root component shouldn't
 * add any content before the html code created by this component. Otherwise
 * it is possible that the dynamic module is rendered over that content and
 * covers it.
 *
 * Derived from [[wsf:WsfComponent]]
 */
object WsfMenu WsfComponent
{
	var __WsfMenu_data;
	var __WsfMenu_data_idx;
	var __WsfMenu_data_action;

	/**
	 * Create boring non-javascript menus if this is set to '1'.
	 * Passing 'nojsmenu: 1' to the constructor sets this this variable.
	 */
	var nojsmenu = 0;

	/**
	 * The width of a menu item.
	 *
	 * Only adjust this if you have extraordinary long descriptions of your
	 * menu items.
	 */
	var size_x = 200;

	/**
	 * The height of a menu element.
	 *
	 * Usuall you do not need to change this to another value;
	 */
	var size_y = 25;

	method __WsfMenu_menu_data_to_html(xpos, ypos, zpos, name, data)
	{
		var subs_html = '';
		var this_html = '<table cellspacing="3" id="${id}__${__WsfMenu_data_idx}" style="position:absolute; left: ${xpos}px; top: ${ypos}px; width:${size_x}px; height:${size_y}px; z-index:${zpos}; ${ypos ? "visibility:hidden;" : ""}" onClick="';

		function switch_visibility(idx) {
			var tmp = "document.getElementById('${id}__${idx}').style.visibility";
			this_html ~= "$tmp = $tmp == 'visible' ? 'hidden' : 'visible';";
		}

		if (defined data) {
			__WsfMenu_data_action[__WsfMenu_data_idx] = data;
			this_html ~= add_javascript("${cgi.url}?sid=${sid}&action=${__WsfMenu_data_idx}");
		} else {
			var sub_xpos = xpos, sub_ypos = ypos, sub_size_y = 0;
			if (ypos) {
				sub_xpos += (size_x / 5) * 4;
				sub_ypos += size_y / 3;
			} else
				sub_ypos += size_y;
			foreach i (data) {
				__WsfMenu_data_idx++;
				switch_visibility(__WsfMenu_data_idx);
				subs_html ~= __WsfMenu_menu_data_to_html(sub_xpos, sub_ypos, zpos+2, i, data[i]);
				sub_size_y += size_y;
				sub_ypos += size_y;
			}

			__WsfMenu_data_idx++;
			switch_visibility(__WsfMenu_data_idx);
			subs_html ~= '<table id="${id}__${__WsfMenu_data_idx}" style="position:absolute; left: ${sub_xpos}px; top: ${sub_ypos-sub_size_y}px; width:${size_x}px; height:${sub_size_y}px; z-index:${zpos+1}; visibility:hidden" bgcolor="#666666"><tr><td>&nbsp;</td></tr></table>\n';
		}
		this_html ~= '"><tr><td bgcolor="#aaaaaa"><font size="-1">&nbsp;<b><nobr>$name</nobr></b></font></td></tr></table>\n';
		return this_html ~ subs_html;
	}

	method __WsfMenu_menu_data_to_html_nojs(name, data)
	{
		var html;
		if (defined data) {
			__WsfMenu_data_action[__WsfMenu_data_idx] = data;
			html ~= <:>
				: <li><a ${add_href("${cgi.url}?sid=${sid}&action=${__WsfMenu_data_idx}")}><nobr>${xml::name}</nobr></a></li>
			</>;
		} else {
			html ~= <:>
				: <li><nobr>${xml::name}</nobr></li>
				: <ul>
			</>;
			foreach i (data) {
				__WsfMenu_data_idx++;
				html ~= __WsfMenu_menu_data_to_html_nojs(i, data[i]);
			}
			html ~= '</ul>\n';
		}
		return html;
	}

	/**
	 * The overloaded [[wsf:WsfComponent.main()]].
	 */
	method main()
	{
		task_co_return();

		if (declared cgi.param.action and
		    defined __WsfMenu_data_action[cgi.param.action])
			__WsfMenu_data_action[cgi.param.action]();

		dirty = 1;
	}
	
	/**
	 * The overloaded [[wsf:WsfComponent.get_html()]].
	 */
	method get_html()
	{
		__WsfMenu_data_idx = 0;
		__WsfMenu_data_action = undef;

		if (nojsmenu) {
			var html = '<div id="$id"><ul>\n';
			foreach i (__WsfMenu_data) {
				__WsfMenu_data_idx++;
				html ~= __WsfMenu_menu_data_to_html_nojs(i, __WsfMenu_data[i]);
			}
			return html ~ '</ul></div>\n';
		}

		var html = '<div id="$id">\n';
		var xpos = 0;
		foreach i (__WsfMenu_data) {
			__WsfMenu_data_idx++;
			html ~= __WsfMenu_menu_data_to_html(xpos, 0, 100, i, __WsfMenu_data[i]);
			xpos += size_x;
		}
		html ~= '<table bgcolor="#444444" style="position:absolute; left: 0px; top: 0px; width:100%; height:${size_y}px; z-index:99"><tr><td>&nbsp;</td></tr></table>\n';
		html ~= '<table style="height:${size_y}px;"><tr><td>&nbsp;</td></tr></table>\n';
		return html ~ '</div>\n';
	}

	/**
	 * The constructor.
	 *
	 * The parameter is a pointer to a hash with the menu structure. The
	 * hash key is the description HTML text of the entry (encode it with
	 * [[xml:encode_xml()]] if needed) and the value is a function pointer
	 * for regular menu entries and hashes again for submenus. E.g.:
	 *
	 *	function get_menu_action(text) {
	 *		return function() {
	 *			debug text;
	 *		};
	 *	}
	 *
	 *	var menu_data = [
	 *		'Menu 1' => [
	 *			'Entry #1' => function() {
	 *				debug "Hello World!";
	 *			},
	 *			'Entry #2' => function() {
	 *				debug "This is a small demo!";
	 *			}
	 *		],
	 *		'Menu 2' => [
	 *			'Closure Example #1' =>
	 *				get_menu_action("Hello World!"),
	 *			'Closure Example #2' =>
	 *				get_menu_action("Another Test!")
	 *		],
	 *		'About' => function() {
	 *			debug "This is a demo program!";
	 *		}
	 *	];
	 *
	 *	var menu = new WsfMenu(menu_data);
	 *
	 * SPL has support for closures. In this example, the get_menu_action()
	 * function is using the concept of closures for storing additional
	 * data with the function pointers assigned to the items in 'Menu 2'.
	 *
	 * Right now, 'nojsmenu: 1' is the only supported option. It sets the
	 * [[.nojsmenu]] variable.
	 */
	method init(menu_data, %options)
	{
		__WsfMenu_data = menu_data;
		if (declared options.nojsmenu)
			nojsmenu = options.nojsmenu;
		return *WsfComponent.init();
	}
}