2 © Copyright 2008 Nokia Corporation. All rights reserved.
\r
4 IMPORTANT: The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia
\r
5 Corporation (“Nokia”) in consideration of your agreement to the following terms. Your use, installation
\r
6 and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If
\r
7 you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example
\r
10 In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia
\r
11 grants you a personal, non-exclusive license, under Nokia’s copyrights in the WRTKit and Example
\r
12 Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,
\r
13 CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60
\r
16 If you redistribute the WRTKit and Example files, you must retain this entire notice in all such
\r
17 redistributions of the WRTKit and Example files.
\r
19 You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products
\r
20 that include the WRTKit and Example files without the prior written explicit agreement with Nokia.
\r
21 Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by
\r
22 Nokia herein, including but not limited to any patent rights that may be infringed by your products that
\r
23 incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files
\r
24 may be incorporated.
\r
26 The WRTKit and Example files are provided on an "AS IS" basis. NOKIA MAKES NO
\r
27 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
\r
28 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
\r
29 PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION
\r
30 ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
\r
32 IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
\r
33 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
\r
34 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
35 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR
\r
36 DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY
\r
37 OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,
\r
38 EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
42 ///////////////////////////////////////////////////////////////////////////////
\r
43 // The SelectionList class implements a single or multi selection control
\r
44 // that lets users select one or more options from a list of options.
\r
47 function SelectionList(id, caption, options, multipleSelection, selected) {
\r
48 if (id != UI_NO_INIT_ID) {
\r
49 this.init(id, caption, options, multipleSelection, selected);
\r
53 // SelectionList inherits from SelectionControl.
\r
54 SelectionList.prototype = new SelectionControl(UI_NO_INIT_ID);
\r
56 // Root element for options.
\r
57 SelectionList.prototype.optionListElement = null;
\r
59 // Array for tracking option elements.
\r
60 SelectionList.prototype.optionElements = null;
\r
62 // Tracking for currently focused option; null if none.
\r
63 SelectionList.prototype.focusedOption = null;
\r
66 SelectionList.prototype.enabled = false;
\r
68 // Initializer - called from constructor.
\r
69 SelectionList.prototype.init = function(id, caption, options, multipleSelection, selected) {
\r
70 uiLogger.debug("SelectionList.init(" + id + ", " + caption + ", " + options + ", " + multipleSelection + ", " + selected + ")");
\r
72 // call superclass initializer
\r
73 SelectionControl.prototype.init.call(this, id, caption, options, multipleSelection, selected);
\r
75 // create option list element
\r
76 this.optionListElement = document.createElement("div");
\r
77 this.controlElement.appendChild(this.optionListElement);
\r
79 // the control defaults to enabled
\r
80 this.enabled = true;
\r
82 // init option element arrays
\r
83 this.optionElements = [];
\r
85 // update the option elements to match the options in this control
\r
86 this.updateOptionElements();
\r
89 // Returns the enabled state.
\r
90 SelectionList.prototype.isEnabled = function() {
\r
91 return this.enabled;
\r
94 // Sets the enabled state.
\r
95 SelectionList.prototype.setEnabled = function(enabled) {
\r
96 uiLogger.debug("SelectionList.setEnabled(" + enabled + ")");
\r
97 // switch the state and update the the control
\r
98 this.enabled = enabled;
\r
99 this.updateOptionElements();
\r
102 // Sets the focused state for the control.
\r
103 // Note: This may not always succeed.
\r
104 SelectionList.prototype.setFocused = function(focused) {
\r
105 uiLogger.debug("SelectionList.setFocused(" + focused + ")");
\r
106 if (this.enabled && this.optionElements.length > 0) {
\r
108 this.optionElements[0].link.focus();
\r
110 this.optionElements[0].link.blur();
\r
115 // Sets the currently selected options. Pass a single option in a single selection
\r
116 // control or an array of selected controls in a multiple selection control. To
\r
117 // deselect all options pass null in a single selection control and an empty array
\r
118 // in a multiple selection control.
\r
119 SelectionList.prototype.setSelected = function(selected) {
\r
120 // call superclass setSelected()
\r
121 SelectionControl.prototype.setSelected.call(this, selected);
\r
122 this.updateStyleFromState();
\r
125 // Sets the options in the control.
\r
126 SelectionList.prototype.setOptions = function(options) {
\r
127 // call superclass setOptions()
\r
128 SelectionControl.prototype.setOptions.call(this, options);
\r
129 this.updateOptionElements();
\r
132 // Updates the option elements for the control element.
\r
133 SelectionList.prototype.updateOptionElements = function() {
\r
134 uiLogger.debug("SelectionControl.updateOptionElements()");
\r
136 // start by removing all current options from the option list element
\r
137 while (this.optionListElement.firstChild != null) {
\r
138 this.optionListElement.removeChild(this.optionListElement.firstChild);
\r
141 // iterate through the options and add (and possibly create) a
\r
142 // properly configured option element for each option
\r
143 for (var i = 0; i < this.options.length; i++) {
\r
144 // get the option and option element we're working on
\r
145 var option = this.options[i];
\r
147 // option, link and text elements for this option
\r
149 var optionLinkElement;
\r
150 var optionTextElement;
\r
152 // get the elements
\r
153 if (i == this.optionElements.length) {
\r
154 // we need to create a new option element...
\r
155 optionElement = document.createElement("div");
\r
157 // ...and a new option link element...
\r
158 optionLinkElement = document.createElement("a");
\r
159 optionLinkElement.href = "JavaScript:void(0)";
\r
161 // ...and a new option text element
\r
162 optionTextElement = document.createElement("span");
\r
164 // hook up event listeners to the element
\r
166 optionLinkElement.addEventListener("focus", function(event) { self.optionFocusStateChanged(event, true); }, false);
\r
167 optionLinkElement.addEventListener("blur", function(event) { self.optionFocusStateChanged(event, false); }, false);
\r
168 optionElement.addEventListener("mouseover", function() { self.hoverStateChanged(true); }, false);
\r
169 optionElement.addEventListener("mouseout", function() { self.hoverStateChanged(false); }, false);
\r
170 optionElement.addEventListener("mousedown", function(event) {
\r
171 self.optionClicked(event)
\r
172 event.stopPropagation();
\r
173 event.preventDefault();
\r
175 optionElement.addEventListener("keydown", function(event) {
\r
176 // center and enter trigger the action
\r
177 if (event.keyCode == 0 || event.keyCode == 13) {
\r
178 self.optionClicked(event)
\r
179 event.stopPropagation();
\r
180 event.preventDefault();
\r
184 // add the elements to the option element array
\r
185 this.optionElements.push({ option: optionElement, link: optionLinkElement, text: optionTextElement });
\r
187 // we already have ready elements so we'll reuse them
\r
188 optionElement = this.optionElements[i].option;
\r
189 optionLinkElement = this.optionElements[i].link;
\r
190 optionTextElement = this.optionElements[i].text;
\r
192 // remove the option link element from its current parent - if any
\r
193 if (optionLinkElement.parentNode != null) {
\r
194 optionLinkElement.parentNode.removeChild(optionLinkElement);
\r
197 // remove the option text element from its current parent - if any
\r
198 if (optionTextElement.parentNode != null) {
\r
199 optionTextElement.parentNode.removeChild(optionTextElement);
\r
203 // set the option text
\r
204 optionTextElement.innerHTML = option.text;
\r
206 // hook up the option to the control
\r
207 if (this.enabled) {
\r
208 // add the option link element to the option element
\r
209 optionElement.appendChild(optionLinkElement);
\r
210 // add the text element to the option element
\r
211 optionLinkElement.appendChild(optionTextElement);
\r
213 // add the text element directly to the control element
\r
214 optionElement.appendChild(optionTextElement);
\r
216 // add the option element to the option list element
\r
217 this.optionListElement.appendChild(optionElement);
\r
220 // update the style
\r
221 this.updateStyleFromState();
\r
224 // Callback for focus state change events.
\r
225 SelectionList.prototype.optionFocusStateChanged = function(event, focused) {
\r
226 uiLogger.debug("SelectionControl.optionFocusStateChanged()");
\r
228 // get the event source option
\r
230 var optionElement = null;
\r
231 for (var i = 0; i < this.optionElements.length; i++) {
\r
232 optionElement = this.optionElements[i];
\r
233 if (optionElement.link == event.currentTarget) {
\r
234 option = this.options[i];
\r
239 // remember the focused option; or null if none is focused
\r
241 this.focusedOption = option;
\r
243 this.focusedOption = null;
\r
246 // call the superclass focus state change handler
\r
247 this.focusStateChanged(focused);
\r
250 // Callback for clicks.
\r
251 SelectionList.prototype.optionClicked = function(event) {
\r
252 uiLogger.debug("SelectionControl.optionClicked()");
\r
254 // bail out if we're not enabled
\r
255 if (!this.enabled) {
\r
259 // get the changed option
\r
261 var optionElement = null;
\r
262 for (var i = 0; i < this.optionElements.length; i++) {
\r
263 optionElement = this.optionElements[i];
\r
264 if (optionElement.option == event.currentTarget) {
\r
265 option = this.options[i];
\r
270 // make sure the option is focused
\r
271 optionElement.link.focus();
\r
273 // toggle the selection
\r
274 if (this.multipleSelection) {
\r
275 // iterate through the selected options and see if this
\r
276 // option is selected. if not then add it to the selection.
\r
277 // if it already is selected then them remove it.
\r
279 for (var i = 0; i < this.selected.length; i++) {
\r
280 if (this.selected[i] == option) {
\r
281 // remove from selected set
\r
283 this.selected.splice(i, 1);
\r
288 // add to the selected set
\r
289 this.selected.push(option);
\r
292 // update the selected option
\r
293 this.selected = option;
\r
296 // update the style
\r
297 this.updateStyleFromState();
\r
299 // notify event listeners
\r
300 this.fireEvent(this.createEvent("SelectionChanged", this.getSelected()));
\r
303 // Resets the state tracking for focus and hover.
\r
304 // Override this in subclasses as required to implement the state reset.
\r
305 SelectionList.prototype.resetFocusState = function() {
\r
306 uiLogger.debug("SelectionList.resetFocusState()");
\r
307 this.hovering = false;
\r
308 this.focused = false;
\r
309 this.focusedOption = null;
\r
310 this.updateStyleFromState();
\r
313 // Updates the style of the control to reflects the state of the control.
\r
314 SelectionList.prototype.updateStyleFromState = function() {
\r
315 uiLogger.debug("SelectionList.updateStyleFromState()");
\r
317 // determine the state name
\r
318 var stateName = this.getStyleStateName();
\r
320 // set element class names
\r
321 this.setClassName(this.rootElement, "Control");
\r
322 this.setClassName(this.controlElement, "ControlElement");
\r
323 this.setClassName(this.assemblyElement, "ControlAssembly ControlAssembly" + stateName);
\r
324 this.setClassName(this.captionElement, "ControlCaption ControlCaption" + stateName);
\r
326 // set option list and option class names
\r
327 this.setClassName(this.optionListElement, "SelectionList SelectionList" + stateName);
\r
328 for (var i = 0; i < this.options.length; i++) {
\r
329 var option = this.options[i];
\r
331 // get the option and option text elements for this option
\r
332 var optionElement = this.optionElements[i].option;
\r
333 var optionTextElement = this.optionElements[i].text;
\r
335 // figure out the option state
\r
336 var optionStateName = this.isSelected(option) ? "Checked" : "Unchecked";
\r
337 if (!this.enabled) {
\r
338 optionStateName += "Disabled";
\r
339 } else if (this.focusedOption == option) {
\r
340 optionStateName += "Focus";
\r
342 optionStateName += "Normal";
\r
345 // set option element class names
\r
346 if (this.multipleSelection) {
\r
347 this.setClassName(optionElement, "SelectionListOptionMulti SelectionListOptionMulti" + optionStateName);
\r
349 this.setClassName(optionElement, "SelectionListOptionSingle SelectionListOptionSingle" + optionStateName);
\r
352 // set option text class names
\r
353 this.setClassName(optionTextElement, "SelectionListOptionText SelectionListOptionText" + stateName);
\r