From cf5ae01ca27fd5dfd1728f2c57bcd001c014feb2 Mon Sep 17 00:00:00 2001 From: ababut Date: Fri, 4 Nov 2011 13:28:09 -0400 Subject: [PATCH 1/9] Modified system.event extension to use a single open event poll for all events. This reduces the active load on the BrowserField thread pool (max 5) and allows all hardware key events to be registered simultaneously. Change applies to both onCoverage and onHardwareKey events. --- api/CommonAPI/sharedglobal/3_xhr.js | 7 +- .../js/common/system_event_dispatcher.js | 144 +++++--- api/system.event/js/common/system_event_ns.js | 2 +- .../system/event/CoverageChangeHandler.java | 77 +++++ .../blackberry/system/event/EventQueue.java | 76 +++++ .../event/ISystemEventExtensionConstants.java | 50 --- .../system/event/ISystemEventListener.java | 32 ++ .../system/event/KeyPressHandler.java | 192 +++++++++++ .../system/event/SystemEventExtension.java | 309 ++++-------------- .../system/event/SystemEventManager.java | 125 +++++++ .../system/event/SystemEventReturnValue.java | 131 ++++++++ 11 files changed, 798 insertions(+), 347 deletions(-) create mode 100644 api/system.event/src/main/java/blackberry/system/event/CoverageChangeHandler.java create mode 100644 api/system.event/src/main/java/blackberry/system/event/EventQueue.java delete mode 100644 api/system.event/src/main/java/blackberry/system/event/ISystemEventExtensionConstants.java create mode 100644 api/system.event/src/main/java/blackberry/system/event/ISystemEventListener.java create mode 100644 api/system.event/src/main/java/blackberry/system/event/KeyPressHandler.java create mode 100644 api/system.event/src/main/java/blackberry/system/event/SystemEventManager.java create mode 100644 api/system.event/src/main/java/blackberry/system/event/SystemEventReturnValue.java diff --git a/api/CommonAPI/sharedglobal/3_xhr.js b/api/CommonAPI/sharedglobal/3_xhr.js index 53db9dd..ed77ec7 100644 --- a/api/CommonAPI/sharedglobal/3_xhr.js +++ b/api/CommonAPI/sharedglobal/3_xhr.js @@ -179,8 +179,11 @@ blackberry.transport.call(url, opts, function (response) { if (callback(response)) { - this.blackberry.transport.poll(url, opts, callback); - } + setTimeout( + function() { this.blackberry.transport.poll(url, opts, callback); }, + 0 + ); + } }); }; })(); diff --git a/api/system.event/js/common/system_event_dispatcher.js b/api/system.event/js/common/system_event_dispatcher.js index faaf52a..f66272d 100644 --- a/api/system.event/js/common/system_event_dispatcher.js +++ b/api/system.event/js/common/system_event_dispatcher.js @@ -13,62 +13,94 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -(function () { - var OK = 0; - var FUNCTION_ON_COVERAGE_CHANGE = "onCoverageChange"; - var FUNCTION_ON_HARDWARE_KEY = "onHardwareKey"; - - var _callbacks = {}; - - function SystemEventDispatcher() { - }; - - function poll(evt, args, handler) { - if (evt == FUNCTION_ON_HARDWARE_KEY) { - var keyCallbacks = _callbacks[evt]; - keyCallbacks = keyCallbacks || {}; - keyCallbacks[args["get"]["key"]] = handler; - _callbacks[evt] = keyCallbacks; - } else { - _callbacks[evt] = handler; - } - - blackberry.transport.poll("blackberry/system/event/" + evt, args, function(response) { - if (response.code < OK) { - // do not invoke callback unless return code is OK +(function () { + var OK = 0, + CHANNEL_CLOSED = 1, + _polling = false, + FUNCTION_ON_COVERAGE_CHANGE = "onCoverageChange", + FUNCTION_ON_HARDWARE_KEY = "onHardwareKey", + _callbacks = {}; + + function poll() { + + blackberry.transport.poll("blackberry/system/event/poll", {}, function(response) { + // do not invoke callback unless return code is OK (negative codes for errors, or channel closed from Java side) + // stop polling if response code is not OK + if (response.code < OK || response.code === CHANNEL_CLOSED) { + _polling = false; return false; } - - var func; - - if (evt == FUNCTION_ON_HARDWARE_KEY) { - func = _callbacks[evt][response.data["key"]]; - } else { - func = _callbacks[evt]; - } - - if (func) { + + var event = response.data.event, + func = (event === FUNCTION_ON_HARDWARE_KEY) ? _callbacks[event][response.data.arg] : _callbacks[event]; + + if (typeof(func) !== "undefined") { func(); } return !!func; }); - }; - - function initPoll(evt, args, handler) { - args = args || {}; - - args["monitor"] = (handler ? true : false); - - poll(evt, { "get" : args }, handler); - }; + + } + + function registerForEvent(evt, args) { + blackberry.transport.call( + "blackberry/system/event/register", + { get : { event : evt, arg : args } }, + function(response) { + if(response.code < OK) { + throw new Error("Unable to register event handler for " + evt + ". Implementation returned: " + response.code); + } + } + ); + + if(!_polling) { + _polling = true; + poll(); + } + } + + function unregisterForEvent(evt, args) { + blackberry.transport.call( + "blackberry/system/event/unregister", + { get : { event : evt, arg : args } }, + function(response) { + if(response.code < OK) { + throw new Error("Unable to unregister event handler for " + evt + ". Implementation returned: " + response.code); + } + } + ); + } + + function SystemEventDispatcher() { + _callbacks[FUNCTION_ON_COVERAGE_CHANGE] = {}; + _callbacks[FUNCTION_ON_HARDWARE_KEY] = {}; + } SystemEventDispatcher.prototype.onCoverageChange = function(onSystemEvent) { - initPoll(FUNCTION_ON_COVERAGE_CHANGE, {}, onSystemEvent); + var listen = (typeof(onSystemEvent) === "function"), + alreadyListening = (typeof(_callbacks[FUNCTION_ON_COVERAGE_CHANGE]) === "function"); + + if(listen) { + //Update the callback reference + _callbacks[FUNCTION_ON_COVERAGE_CHANGE] = onSystemEvent; + + //If we are already listening, don't re-register + if(!alreadyListening) { + //Start listening for this event + registerForEvent(FUNCTION_ON_COVERAGE_CHANGE); + } + } else { + //Update the callback reference + _callbacks[FUNCTION_ON_COVERAGE_CHANGE] = undefined; + if(alreadyListening) { + unregisterForEvent(FUNCTION_ON_COVERAGE_CHANGE); + } + } }; - SystemEventDispatcher.prototype.onHardwareKey = function(key, onSystemEvent) { + SystemEventDispatcher.prototype.onHardwareKey = function(onSystemEvent, key) { switch (key) { case blackberry.system.event.KEY_BACK: case blackberry.system.event.KEY_MENU: @@ -82,9 +114,27 @@ default: throw new Error("key parameter must be one of the pre-defined KEY_* constants"); } - - initPoll(FUNCTION_ON_HARDWARE_KEY, { "key" : key }, onSystemEvent); + + var listen = (typeof(onSystemEvent) === "function"), + alreadyListening = (typeof(_callbacks[FUNCTION_ON_HARDWARE_KEY][key]) === "function"); + + if(listen) { + //Update the callback reference + _callbacks[FUNCTION_ON_HARDWARE_KEY][key] = onSystemEvent; + + //Only register with the implementation if we're not already listening + if(!alreadyListening) { + //Start listening for this event + registerForEvent(FUNCTION_ON_HARDWARE_KEY, key); + } + } else { + //Update the callback reference + _callbacks[FUNCTION_ON_HARDWARE_KEY][key] = undefined; + if(alreadyListening) { + unregisterForEvent(FUNCTION_ON_HARDWARE_KEY, key); + } + } }; blackberry.Loader.javascriptLoaded("blackberry.system.event", SystemEventDispatcher); -})(); +}()); diff --git a/api/system.event/js/common/system_event_ns.js b/api/system.event/js/common/system_event_ns.js index b93db80..6b8d2e2 100644 --- a/api/system.event/js/common/system_event_ns.js +++ b/api/system.event/js/common/system_event_ns.js @@ -18,7 +18,7 @@ function SystemEvent(disp) { this.onCoverageChange = function(onSystemEvent) { return disp.onCoverageChange(onSystemEvent); }; - this.onHardwareKey = function(key, onSystemEvent) { return disp.onHardwareKey(key, onSystemEvent); }; + this.onHardwareKey = function(key, onSystemEvent) { return disp.onHardwareKey(onSystemEvent, key); }; } SystemEvent.prototype.__defineGetter__("KEY_BACK", function() { return 0; }); diff --git a/api/system.event/src/main/java/blackberry/system/event/CoverageChangeHandler.java b/api/system.event/src/main/java/blackberry/system/event/CoverageChangeHandler.java new file mode 100644 index 0000000..a3a8337 --- /dev/null +++ b/api/system.event/src/main/java/blackberry/system/event/CoverageChangeHandler.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blackberry.system.event; + +import blackberry.system.event.ISystemEventListener; + +import net.rim.device.api.system.CoverageInfo; +import net.rim.device.api.system.CoverageStatusListener; + +/** + * Coverage listener implementation. Proxy for system coverage listener that + * notifies manager generically of coverage change events. + * + * @author ababut + */ +public class CoverageChangeHandler { + private ISystemEventListener _manager; + + private CoverageStatusListener _currentCoverageMonitor; + + CoverageChangeHandler(ISystemEventListener manager) { + _manager = manager; + } + + /** + * Creates a listener if not present and registers it. + * + */ + public void listen() { + if( _currentCoverageMonitor == null ) { + _currentCoverageMonitor = new CoverageStatusListener() { + public void coverageStatusChanged( int newCoverage ) { + //Notify manager of coverage changed event + //TODO: Add new coverage to the event argument if JS cares about it + _manager.onSystemEvent(_manager.EVENT_COV_CHANGE, ""); + } + }; + + CoverageInfo.addListener(_currentCoverageMonitor); + } + } + + /** + * Removes system listener if present. + * + */ + public void stopListening() { + if(_currentCoverageMonitor != null) { + CoverageInfo.removeListener(_currentCoverageMonitor); + //Explicitly null it out to avoid memory leaks + _currentCoverageMonitor = null; + } + } + + /** + * Indicates listener status + * + * @return true if listener is active + */ + public boolean isListening() { + return (_currentCoverageMonitor != null); + } +} diff --git a/api/system.event/src/main/java/blackberry/system/event/EventQueue.java b/api/system.event/src/main/java/blackberry/system/event/EventQueue.java new file mode 100644 index 0000000..82a27f1 --- /dev/null +++ b/api/system.event/src/main/java/blackberry/system/event/EventQueue.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blackberry.system.event; + +import java.util.Vector; +import blackberry.system.event.SystemEventReturnValue; + + /** Thread safe queue implementation based on Vector. + * + * @author ababut + */ +public class EventQueue { + private Vector _queue; + private Object _lock; + + EventQueue() { + _queue = new Vector(); + _lock = new Object(); + } + + /** + * Queues a SystemReturnValue object and signals the lock that there are items + * waiting. + * + * @param event the event to queue up + */ + public void enqueue(SystemEventReturnValue event) { + synchronized(_lock) { + _queue.addElement(event); + _lock.notify(); + } + } + + /** + * Removes first SystemReturnValue object in queue. If queue is empty, wait + * on lock until signalled. + * + * @param event the event to queue up + */ + public SystemEventReturnValue dequeueWaitIfEmpty() { + SystemEventReturnValue result = null; + + if(_queue.isEmpty()) { + try { + synchronized(_lock) { + _lock.wait(); + } + } catch(InterruptedException e) { + System.out.println("InterrupedException while waiting on event queue"); + throw new RuntimeException("Polling thread interrupted while waiting."); + } + + } + + synchronized(_lock) { + result = (SystemEventReturnValue)_queue.elementAt(0); + _queue.removeElementAt(0); + } + + return result; + } +} diff --git a/api/system.event/src/main/java/blackberry/system/event/ISystemEventExtensionConstants.java b/api/system.event/src/main/java/blackberry/system/event/ISystemEventExtensionConstants.java deleted file mode 100644 index dd5ddb7..0000000 --- a/api/system.event/src/main/java/blackberry/system/event/ISystemEventExtensionConstants.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010-2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package blackberry.system.event; - -/** - * interface ISystemEventExtensionConstants contains constants - * which are need by SystemEventExtension - * @author rtse - */ -public interface ISystemEventExtensionConstants { - // Feature name - public final static String FEATURE_ID = "blackberry.system.event"; - - public static final String REQ_FUNCTION_ON_HARDWARE_KEY = "onHardwareKey"; - public static final String REQ_FUNCTION_ON_COVERAGE_CHANGE = "onCoverageChange"; - - public static final String ARG_MONITOR = "monitor"; - public static final String ARG_KEY = "key"; - - public static final String KEY_BACK = "KEY_BACK"; - public static final String KEY_MENU = "KEY_MENU"; - public static final String KEY_CONVENIENCE_1 = "KEY_CONVENIENCE_1"; - public static final String KEY_CONVENIENCE_2 = "KEY_CONVENIENCE_2"; - public static final String KEY_STARTCALL = "KEY_STARTCALL"; - public static final String KEY_ENDCALL = "KEY_ENDCALL"; - public static final String KEY_VOLUME_UP = "KEY_VOLUMEUP"; - public static final String KEY_VOLUME_DOWN = "KEY_VOLUMEDOWN"; - - public static final int IKEY_BACK = 0; - public static final int IKEY_MENU = 1; - public static final int IKEY_CONVENIENCE_1 = 2; - public static final int IKEY_CONVENIENCE_2 = 3; - public static final int IKEY_STARTCALL = 4; - public static final int IKEY_ENDCALL = 5; - public static final int IKEY_VOLUME_DOWN = 6; - public static final int IKEY_VOLUME_UP = 7; -} diff --git a/api/system.event/src/main/java/blackberry/system/event/ISystemEventListener.java b/api/system.event/src/main/java/blackberry/system/event/ISystemEventListener.java new file mode 100644 index 0000000..d471140 --- /dev/null +++ b/api/system.event/src/main/java/blackberry/system/event/ISystemEventListener.java @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package blackberry.system.event; + + /** Interface implemented by the class that will generically signalled that + * an event has occurred. Contains several constants for convenience. + * + * @author ababut + */ +public interface ISystemEventListener { + + static final String EVENT_COV_CHANGE = "onCoverageChange"; + static final String EVENT_HARDWARE_KEY = "onHardwareKey"; + + void onSystemEvent(String event, String eventArg); + +} diff --git a/api/system.event/src/main/java/blackberry/system/event/KeyPressHandler.java b/api/system.event/src/main/java/blackberry/system/event/KeyPressHandler.java new file mode 100644 index 0000000..7020a1b --- /dev/null +++ b/api/system.event/src/main/java/blackberry/system/event/KeyPressHandler.java @@ -0,0 +1,192 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blackberry.system.event; + +import net.rim.device.api.system.Application; +import net.rim.device.api.system.KeyListener; +import net.rim.device.api.ui.Keypad; + +/** + * Key listener implementation. Proxy for system key listener that + * notifies manager generically of relevant key events. + * + * @author ababut + */ +class KeyPressHandler { + private static final int IKEY_BACK = 0; + private static final int IKEY_MENU = 1; + private static final int IKEY_CONVENIENCE_1 = 2; + private static final int IKEY_CONVENIENCE_2 = 3; + private static final int IKEY_STARTCALL = 4; + private static final int IKEY_ENDCALL = 5; + private static final int IKEY_VOLUME_DOWN = 6; + private static final int IKEY_VOLUME_UP = 7; + + private ISystemEventListener _manager; + + private KeyListener _keyMonitor; + + private boolean[] _listenerForKey = new boolean[] { false, false, false, false, false, false, false, false}; + + KeyPressHandler(ISystemEventListener manager) { + _manager = manager; + } + + /** + * Creates a listener if not present and registers it. Listener is active if + * we are listening for at least one key. + * + * @param forKey the key code to listen for + */ + public void listen(String forKey) { + int keyToListenFor = Integer.parseInt(forKey); + + if(keyToListenFor < 0 || keyToListenFor > _listenerForKey.length) { + throw new IllegalArgumentException("Invalid key code requested [" + keyToListenFor + "]"); + } + + if(_keyMonitor == null) { + + //Anonymous implementation of the net.rim.device.api.system.KeyListener interface + _keyMonitor = new KeyListener() { + + /** + * @see net.rim.device.api.system.KeyListener#keyDown(int, int) + */ + public boolean keyDown( int keycode, int time ) { + int keyPressed = Keypad.key( keycode ); + int event; + + switch( keyPressed ) { + case Keypad.KEY_CONVENIENCE_1: + event = IKEY_CONVENIENCE_1; + break; + case Keypad.KEY_CONVENIENCE_2: + event = IKEY_CONVENIENCE_2; + break; + case Keypad.KEY_MENU: + event = IKEY_MENU; + break; + case Keypad.KEY_SEND: + event = IKEY_STARTCALL; + break; + case Keypad.KEY_END: + event = IKEY_ENDCALL; + break; + case Keypad.KEY_ESCAPE: + event = IKEY_BACK; + break; + case Keypad.KEY_VOLUME_DOWN: + event = IKEY_VOLUME_DOWN; + break; + case Keypad.KEY_VOLUME_UP: + event = IKEY_VOLUME_UP; + break; + default: + return false; + } + + //If we're listening for this hardware key, queue up an event for it + if(_listenerForKey[event]) { + _manager.onSystemEvent(_manager.EVENT_HARDWARE_KEY, String.valueOf(event)); + + return true; + } + + return false; + } + + /** + * @see net.rim.device.api.system.KeyListener#keyChar(char, int, int) + */ + public boolean keyChar( char arg0, int arg1, int arg2 ) { + return false; + } + + /** + * @see net.rim.device.api.system.KeyListener#keyRepeat(int, int) + */ + public boolean keyRepeat( int arg0, int arg1 ) { + return false; + } + + /** + * @see net.rim.device.api.system.KeyListener#keyStatus(int, int) + */ + public boolean keyStatus( int arg0, int arg1 ) { + return false; + } + + /** + * @see net.rim.device.api.system.KeyListener#keyUp(int, int) + */ + public boolean keyUp( int arg0, int arg1 ) { + return false; + } + }; + + Application.getApplication().addKeyListener(_keyMonitor); + } + + //Mark our event as listening + _listenerForKey[keyToListenFor] = true; + } + + /** + * Unregisters a listener for a given key. + * + * @param forKey the key code to stop listening for + */ + public void stopListening(String forKey) { + int keyToStop = Integer.parseInt(forKey); + + if(keyToStop < 0 || keyToStop > _listenerForKey.length) { + throw new IllegalArgumentException("Invalid key code requested [" + keyToStop + "]"); + } + + //Mark key as not listening + _listenerForKey[keyToStop] = false; + + //De-register application listener if we are no longer listening for any keys + if(!isListening()) { + Application.getApplication().removeKeyListener(_keyMonitor); + _keyMonitor = null; + } + } + + /** + * Unregisters all active listeners. + */ + public void stopListeningToAll() { + for(int i = _listenerForKey.length - 1; i >= 0; i--) { + if (_listenerForKey[i]) stopListening(String.valueOf(i)); + } + } + + /** + * Indicates listener status + * + * @return true if listener is active + */ + public boolean isListening() { + for(int i = _listenerForKey.length - 1; i >= 0; i--) { + if (_listenerForKey[i]) return true; + } + + return false; + } +} diff --git a/api/system.event/src/main/java/blackberry/system/event/SystemEventExtension.java b/api/system.event/src/main/java/blackberry/system/event/SystemEventExtension.java index be6de94..87b76c5 100644 --- a/api/system.event/src/main/java/blackberry/system/event/SystemEventExtension.java +++ b/api/system.event/src/main/java/blackberry/system/event/SystemEventExtension.java @@ -13,304 +13,119 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package blackberry.system.event; -import java.util.Vector; - import org.w3c.dom.Document; import net.rim.device.api.browser.field2.BrowserField; import net.rim.device.api.script.ScriptEngine; -import net.rim.device.api.system.CoverageInfo; -import net.rim.device.api.system.CoverageStatusListener; -import net.rim.device.api.system.KeyListener; -import net.rim.device.api.ui.Keypad; -import net.rim.device.api.util.IntEnumeration; -import net.rim.device.api.util.IntHashtable; + import net.rim.device.api.util.SimpleSortingVector; import net.rim.device.api.web.WidgetConfig; import net.rim.device.api.web.WidgetException; import blackberry.common.util.JSUtilities; -import blackberry.common.util.json4j.JSONObject; + import blackberry.core.IJSExtension; import blackberry.core.JSExtensionRequest; import blackberry.core.JSExtensionResponse; -import blackberry.core.JSExtensionReturnValue; + +import blackberry.system.event.SystemEventManager; +import blackberry.system.event.SystemEventReturnValue; /** * JavaScript extension for blackberry.system.event
* * Uses long-polling to handle callbacks.
* - * When user starts listening for an event (by specifying a callback function), the following happens: + * When a callback is registered in JavaScript, the following sequence of events takes place: *
    - *
  1. The current thread blocks till the desired event occurs.
  2. - *
  3. The thread is notified causing the HTTP request to return.
  4. - *
  5. The callback function gets invoked on the client side.
  6. - *
  7. Client side immediately issues a new request to listen for the event. (cycle continues until user unregisters the callback)
  8. + *
  9. A "register" call is made with the event name.
  10. + *
  11. If the event is recognized and successfully registered with the BlackBerry API, OK is returned.
  12. + *
  13. When the system event occurs, it is queued in an event queue for consumption by the "poll" call.
  14. + *
  15. The JavaScript layer makes a "poll" call as long as we are listening to at least one event. It waits on the event queue until an event occurs, at which point it returns it.
  16. + *
  17. Client side immediately issues a new request to listen for the event.
  18. + *
  19. Cycle continues until user unregisters the last callback and a stop listening event is sent back instead to release the last open polling connection.
  20. *
- * @author rtse + * @author ababut */ -public class SystemEventExtension implements IJSExtension, ISystemEventExtensionConstants, KeyListener { - private static Vector SUPPORTED_METHODS; - - static { - SUPPORTED_METHODS = new Vector(); - SUPPORTED_METHODS.addElement( REQ_FUNCTION_ON_COVERAGE_CHANGE ); - SUPPORTED_METHODS.addElement( REQ_FUNCTION_ON_HARDWARE_KEY ); - } +public class SystemEventExtension implements IJSExtension { + private static final String FUNCTION_REGISTER = "register"; + private static final String FUNCTION_UNREGISTER = "unregister"; + private static final String FUNCTION_POLL = "poll"; private static String[] JS_FILES = { "system_event_dispatcher.js", "system_event_ns.js" }; - private CoverageMonitor _currentCoverageMonitor; - private IntHashtable _keyRegistry = new IntHashtable(); - - public String[] getFeatureList() { - String[] featureList; - featureList = new String[ 1 ]; - featureList[ 0 ] = FEATURE_ID; - return featureList; - } - - private static boolean parseBoolean( String str ) { - return ( str != null && str.equals( Boolean.TRUE.toString() ) ); - } - - private void reset() { - if( _currentCoverageMonitor != null && _currentCoverageMonitor.isListening() ) { - _currentCoverageMonitor.stop(); - } - _currentCoverageMonitor = null; - - if( !_keyRegistry.isEmpty() ) { - IntEnumeration keys = _keyRegistry.keys(); - - while( keys.hasMoreElements() ) { - Object tmp = _keyRegistry.remove( keys.nextElement() ); - - // even though the key is no longer being monitored, we still need to release any thread that is waiting on its - // lock - if( tmp != null ) { - synchronized( tmp ) { - tmp.notify(); - } - } - } - } - } + private SystemEventManager _eventManager = new SystemEventManager(); /** - * Implements invoke() of interface IJSExtension. Methods of extension will be called here. + * Implements invoke() of interface IJSExtension. Responsible for parsing request method and its optional argument. + * The operation is one of (register/unregister/poll). + * The event argument is one of (onCoverageChange/onHardwareKey). + * The arg argument is optional and applies only to the hardware key event. It contains a numeric constant representing the key to listen for. + * * @throws WidgetException */ public void invoke( JSExtensionRequest request, JSExtensionResponse response ) throws WidgetException { - String method = request.getMethodName(); + String op = request.getMethodName(); Object[] args = request.getArgs(); - String msg = ""; - int code = JSExtensionReturnValue.SUCCESS; - JSONObject data = new JSONObject(); - JSONObject returnValue; - - if( !SUPPORTED_METHODS.contains( method ) ) { - throw new WidgetException( "Undefined method: " + method ); - } - + + //Event and optional argument we'll be operating on, default to empty string to avoid NPEs + String event = (args != null && args.length > 0) ? (String) request.getArgumentByName( "event" ) : ""; + String eventArg = (args != null && args.length > 1) ? (String) request.getArgumentByName( "arg" ) : ""; + + SystemEventReturnValue returnValue = null; + + //Dispatch the function call or complain that we don't recognize it try { - if( method.equals( REQ_FUNCTION_ON_COVERAGE_CHANGE ) ) { - if( args != null && args.length > 0 ) { - String monitor = (String) request.getArgumentByName( ARG_MONITOR ); - - data.put( ARG_MONITOR, monitor ); - - listenToCoverageChange( parseBoolean( monitor ) ); - } - } else if( method.equals( REQ_FUNCTION_ON_HARDWARE_KEY ) ) { - if( args != null && args.length > 1 ) { - int key = Integer.parseInt( (String) request.getArgumentByName( ARG_KEY ) ); - String monitor = (String) request.getArgumentByName( ARG_MONITOR ); - - data.put( ARG_MONITOR, monitor ); - data.put( ARG_KEY, key ); - - listenToKey( parseBoolean( monitor ), key ); - } - } - } catch( Exception e ) { - msg = e.getMessage(); - code = JSExtensionReturnValue.FAIL; - } - - returnValue = new JSExtensionReturnValue( msg, code, data ).getReturnValue(); - response.setPostData( returnValue.toString().getBytes() ); - } - - private void listenToCoverageChange( boolean register ) throws Exception { - if( register ) { - if( _currentCoverageMonitor == null ) { - _currentCoverageMonitor = new CoverageMonitor(); - } - - // blocks - _currentCoverageMonitor.run(); - - // this block is hit when the thread gets notified by the de-registration - // throw exception to indicate to JS client that callback should not be invoked - if( !_currentCoverageMonitor.isListening() ) { - _currentCoverageMonitor = null; - throw new Exception( "Coverage change is no longer monitored" ); - } - } else { - if( _currentCoverageMonitor != null && _currentCoverageMonitor.isListening() ) { - _currentCoverageMonitor.stop(); + if(FUNCTION_REGISTER.equals(op)) { + _eventManager.listenFor(event, eventArg); + returnValue = SystemEventReturnValue.getSuccessForOp(FUNCTION_REGISTER, event); + } else if(FUNCTION_UNREGISTER.equals(op)) { + _eventManager.stopListeningFor(event, eventArg); + returnValue = SystemEventReturnValue.getSuccessForOp(FUNCTION_UNREGISTER, event); + } else if(FUNCTION_POLL.equals(op)) { + returnValue = _eventManager.getNextWaitingEvent(); + } else { + returnValue = SystemEventReturnValue.INVALID_METHOD; } + } catch (RuntimeException e) { + returnValue = SystemEventReturnValue.getErrorForOp(op, event); } + + response.setPostData( returnValue.getJSExtensionReturnValue().getReturnValue().toString().getBytes() ); } /** - * Helper class to implement CoverageStatusListener + * @see blackberry.core.IJSExtension#getFeatureList() */ - private class CoverageMonitor implements CoverageStatusListener { - private Object _lock; - private boolean _listening; - - public CoverageMonitor() { - _lock = new Object(); - _listening = true; - CoverageInfo.addListener( this ); - } - - public void coverageStatusChanged( int newCoverage ) { - synchronized( _lock ) { - _lock.notify(); - } - } - - public void run() throws InterruptedException { - synchronized( _lock ) { - _lock.wait(); - } - } - - public void stop() { - CoverageInfo.removeListener( this ); - _listening = false; - synchronized( _lock ) { - _lock.notify(); - } - } - - public boolean isListening() { - return _listening; - } - } - - public boolean keyChar( char arg0, int arg1, int arg2 ) { - return false; - } - - private void listenToKey( boolean register, int key ) throws Exception { - Object lock = new Object(); - - if( register ) { - synchronized( lock ) { - _keyRegistry.put( key, lock ); - - if( !_keyRegistry.isEmpty() ) { - // wait on the lock for the specific key - lock.wait(); - } - } - - // this block is hit when the thread gets notified by the de-registration - // throw exception to indicate to JS client that callback should not be invoked - if( !_keyRegistry.containsKey( key ) ) { - throw new Exception( "Key " + key + " is no longer monitored" ); - } - } else { - Object tmp = _keyRegistry.remove( key ); - - // even though the key is no longer being monitored, we still need to release any thread that is waiting on its - // lock - if( tmp != null ) { - synchronized( tmp ) { - tmp.notify(); - } - } - } + public String[] getFeatureList() { + return new String[] { "blackberry.system.event" }; } /** - * @see net.rim.device.api.system.KeyListener#keyDown(int, int) + * @see blackberry.core.IJSExtension#loadFeature(String, String, Document, ScriptEngine, jsInjectionPaths) */ - public boolean keyDown( int keycode, int time ) { - int keyPressed = Keypad.key( keycode ); - int event; - - switch( keyPressed ) { - case Keypad.KEY_CONVENIENCE_1: - event = IKEY_CONVENIENCE_1; - break; - case Keypad.KEY_CONVENIENCE_2: - event = IKEY_CONVENIENCE_2; - break; - case Keypad.KEY_MENU: - event = IKEY_MENU; - break; - case Keypad.KEY_SEND: - event = IKEY_STARTCALL; - break; - case Keypad.KEY_END: - event = IKEY_ENDCALL; - break; - case Keypad.KEY_ESCAPE: - event = IKEY_BACK; - break; - case Keypad.KEY_VOLUME_DOWN: - event = IKEY_VOLUME_DOWN; - break; - case Keypad.KEY_VOLUME_UP: - event = IKEY_VOLUME_UP; - break; - default: - return false; - } - - if( _keyRegistry.containsKey( event ) ) { - Object lock = _keyRegistry.get( event ); - synchronized( lock ) { - // notify the thread waiting for that specific key's lock - lock.notify(); - } - - return true; - } - - return false; - } - - public boolean keyRepeat( int arg0, int arg1 ) { - return false; - } - - public boolean keyStatus( int arg0, int arg1 ) { - return false; - } - - public boolean keyUp( int arg0, int arg1 ) { - return false; - } - public void loadFeature( String feature, String version, Document document, ScriptEngine scriptEngine, SimpleSortingVector jsInjectionPaths ) { JSUtilities.loadJS( scriptEngine, JS_FILES, jsInjectionPaths ); } + /** + * @see blackberry.core.IJSExtension#register(WidgetConfig, BrowserField) + */ public void register( WidgetConfig widgetConfig, BrowserField browserField ) { - } + /** + * @see blackberry.core.IJSExtension#unloadFeatures() + */ public void unloadFeatures() { - // Clear states when page is done + // Clear event listeners when page is done reset(); } + + private void reset() { + _eventManager.shutDown(); + } } diff --git a/api/system.event/src/main/java/blackberry/system/event/SystemEventManager.java b/api/system.event/src/main/java/blackberry/system/event/SystemEventManager.java new file mode 100644 index 0000000..f23d4f4 --- /dev/null +++ b/api/system.event/src/main/java/blackberry/system/event/SystemEventManager.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blackberry.system.event; + +/** Manages registering/deregistering and consumption of event objects. + * + * This class will register and queue up system events. It will pass itself to + * system event handlers to be notified when a system event has occurred. The + * event is transformed to a WebWorks text-based return object and queued in a + * blocking queue. + * + * @author ababut + */ +public class SystemEventManager implements ISystemEventListener { + //The blocking event queue + private EventQueue _eventQueue; + + //System event handlers + private CoverageChangeHandler _coverageHandler = null; + private KeyPressHandler _keyHandler = null; + + public SystemEventManager() { + _eventQueue = new EventQueue(); + _coverageHandler = new CoverageChangeHandler(this); + _keyHandler = new KeyPressHandler(this); + } + + /** + * Validates and registers the requested event. + * + * @param event the event to listen for + * @param arg optional argument to be passed to the event handler + */ + public void listenFor(String event, String arg) { + if(EVENT_COV_CHANGE.equals(event)) { + _coverageHandler.listen(); + } else if(EVENT_HARDWARE_KEY.equals(event)) { + if(arg == null || arg.length() == 0) { + throw new IllegalArgumentException("Expected [key] argument to register listener."); + } + + _keyHandler.listen(arg); + } else { + throw new IllegalArgumentException("Unable to register unknown event [" + event + "]"); + } + } + + /** + * Validates and unregisters the requested event. + * + * @param event the event to listen for + * @param arg optional argument to be passed to the event handler + */ + public void stopListeningFor(String event, String arg) { + //Signal appropriate event handler to stop listening + if(EVENT_COV_CHANGE.equals(event)) { + _coverageHandler.stopListening(); + } else if(EVENT_HARDWARE_KEY.equals(event)) { + if(arg == null || arg.length() == 0) { + throw new IllegalArgumentException("Expected [key] argument to unregister listener."); + } + + _keyHandler.stopListening(arg); + } else { + throw new IllegalArgumentException("Unable to unregister unknown event [" + event + "]"); + } + + //If there are no more active listeners, queue up a channel closed message to + //close any lingering poll requests + if(!hasActiveListeners()) { + _eventQueue.enqueue(SystemEventReturnValue.CHANNEL_CLOSED); + } + } + + /** + * Checks if any handlers are listening to system events and unregisters them. + */ + public void shutDown() { + if(_coverageHandler.isListening()) { + _coverageHandler.stopListening(); + } + + if(_keyHandler.isListening()) { + _keyHandler.stopListeningToAll(); + } + } + + private boolean hasActiveListeners() { + return _coverageHandler.isListening() || _keyHandler.isListening(); + } + + /** + * Blocking call that returns next event queued. + * + * @return a return value object representing a queued system event + */ + public SystemEventReturnValue getNextWaitingEvent() { + return _eventQueue.dequeueWaitIfEmpty(); + } + + /** + * Called by system event handlers to queue up a system event that has occurred. + * The event is converted into a return value object. + * + * @param eventName name of event + * @param eventArg optional argument describing the event + */ + public void onSystemEvent(String eventName, String eventArg) { + _eventQueue.enqueue(SystemEventReturnValue.getReturnValueForEvent(eventName, eventArg)); + } +} diff --git a/api/system.event/src/main/java/blackberry/system/event/SystemEventReturnValue.java b/api/system.event/src/main/java/blackberry/system/event/SystemEventReturnValue.java new file mode 100644 index 0000000..12b00a6 --- /dev/null +++ b/api/system.event/src/main/java/blackberry/system/event/SystemEventReturnValue.java @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blackberry.system.event; + +import blackberry.common.util.json4j.JSONObject; +import blackberry.common.util.json4j.JSONException; + +import blackberry.core.JSExtensionReturnValue; + +/** + * Helper class for creating return value objects. + * + * @author ababut + */ +class SystemEventReturnValue { + private static final int RC_FAIL = JSExtensionReturnValue.FAIL; + private static final int RC_SUCCESS = JSExtensionReturnValue.SUCCESS; + private static final int RC_CHANNEL_CLOSED = 1; + + /** + * Constant return value for invalid methods requested + */ + public static final SystemEventReturnValue INVALID_METHOD = new SystemEventReturnValue(new JSExtensionReturnValue( + "Invalid method requested", + RC_FAIL, + new JSONObject() + )); + + /** + * Constant return value for channel closed event + */ + public static final SystemEventReturnValue CHANNEL_CLOSED = new SystemEventReturnValue(new JSExtensionReturnValue( + "Listening channel closed", + RC_CHANNEL_CLOSED, + new JSONObject() + )); + + /** + * Composes a success return value for a given event and its arguments + * + * @param event a String representing the event that occurred + * @param eventArg optional arguments that further describe the event + */ + public static SystemEventReturnValue getReturnValueForEvent(String event, String eventArg) { + return new SystemEventReturnValue(new JSExtensionReturnValue( + "Event occurred", + RC_SUCCESS, + createJSONReturnData(event, eventArg) + )); + } + + /** + * Composes a error return value for a given event and its arguments + * + * @param event a String representing the event that occurred + * @param eventArg optional arguments that further describe the event + */ + public static SystemEventReturnValue getErrorForOp(String method, String arg) { + return new SystemEventReturnValue(new JSExtensionReturnValue( + "Error calling [" + method + "] with [" + arg + "]", + RC_FAIL, + new JSONObject() + )); + } + + /** + * Composes a generic successful call to method return value + * + * @param method a String representing the method serviced + * @param arg arguments passed to the method + */ + public static SystemEventReturnValue getSuccessForOp(String method, String arg) { + return new SystemEventReturnValue(new JSExtensionReturnValue( + "Success calling [" + method + "] with [" + arg + "]", + RC_SUCCESS, + new JSONObject() + )); + } + + private static JSONObject createJSONReturnData(String event, String eventArg) { + StringBuffer jsonBuilder = new StringBuffer(); + + jsonBuilder.append("{event:"); + jsonBuilder.append( (null == event || "".equals(event)) ? "" : event); + + if(null != eventArg && eventArg.length() > 0) { + jsonBuilder.append(",arg:" + eventArg); + } + + jsonBuilder.append('}'); + + JSONObject retval = null; + + try { + retval = new JSONObject(jsonBuilder.toString()); + } catch (JSONException e) { + throw new RuntimeException("Error creating JSON return value for event [" + event + "] with arg [" + eventArg + "]"); + } + + return retval; + } + + private JSExtensionReturnValue _extReturnValue; + + private SystemEventReturnValue(JSExtensionReturnValue extensionReturnValue) { + _extReturnValue = extensionReturnValue; + } + + /** + * Returns the wrapped JSExtensionReturnValue object + * + * @see blackberry.core.JSExtensionReturnValue + */ + public JSExtensionReturnValue getJSExtensionReturnValue() { + return _extReturnValue; + } +} From 0529f6dbc49d9fb2c013db23fb3b3ec2ff4449b3 Mon Sep 17 00:00:00 2001 From: Tim Neil Date: Thu, 24 Nov 2011 13:36:04 -0500 Subject: [PATCH 2/9] added support for rim:orientation --- .../src/blackberry/web/widget/Widget.java | 12 ++++++++ .../web/widget/impl/WidgetConfigImpl.java | 17 +++++++++++ .../net/rim/tumbler/config/WidgetConfig.java | 19 +++++++++++++ .../serialize/WidgetConfig_v1Serializer.java | 6 ++++ .../net/rim/tumbler/xml/ConfigXMLParser.java | 28 +++++++++++++++++++ 5 files changed, 82 insertions(+) diff --git a/framework/src/blackberry/web/widget/Widget.java b/framework/src/blackberry/web/widget/Widget.java index 6f67452..adc0079 100644 --- a/framework/src/blackberry/web/widget/Widget.java +++ b/framework/src/blackberry/web/widget/Widget.java @@ -53,6 +53,18 @@ public Widget( WidgetConfig wConfig, String locationURI ) { initialize(); _locationURI = locationURI; + // Set our orientation + WidgetConfigImpl configImpl = (WidgetConfigImpl) _wConfig; + if (configImpl.isOrientationDefined()) { + int direction; + if (configImpl.getOrientation() == 0) { + direction = net.rim.device.api.system.Display.DIRECTION_PORTRAIT; + } else { + direction = net.rim.device.api.system.Display.DIRECTION_LANDSCAPE; + } + net.rim.device.api.ui.Ui.getUiEngineInstance().setAcceptableDirections(direction); + } + // Create PageManager PageManager pageManager = new PageManager( this, (WidgetConfigImpl) _wConfig ); diff --git a/framework/src/blackberry/web/widget/impl/WidgetConfigImpl.java b/framework/src/blackberry/web/widget/impl/WidgetConfigImpl.java index 06caf6b..1d1864c 100644 --- a/framework/src/blackberry/web/widget/impl/WidgetConfigImpl.java +++ b/framework/src/blackberry/web/widget/impl/WidgetConfigImpl.java @@ -92,6 +92,10 @@ public abstract class WidgetConfigImpl implements WidgetConfig { protected int _transitionType; protected int _transitionDuration; protected int _transitionDirection; + + // orientation configuration + protected int _orientation; + protected boolean _orientationDefined; // caches configuration protected boolean _cacheEnabled; @@ -137,6 +141,10 @@ protected WidgetConfigImpl() { _transitionType = TransitionConstants.TRANSITION_NONE; _transitionDuration = TransitionConstants.DEFAULT_DURATION; _transitionDirection = TransitionConstants.DIRECTION_LEFT; + + // Set default orientation values + _orientationDefined = false; + _orientation = -1; // Set default value of cache configuration _cacheEnabled = true; @@ -282,6 +290,15 @@ public int getTransitionDuration() { public int getTransitionDirection() { return _transitionDirection; } + + // Getters of orientation + public boolean isOrientationDefined() { + return _orientationDefined; + } + + public int getOrientation() { + return _orientation; + } // Getters of cache configuration public boolean isCacheEnabled() { diff --git a/packager/src/net/rim/tumbler/config/WidgetConfig.java b/packager/src/net/rim/tumbler/config/WidgetConfig.java index ee93553..a41351f 100644 --- a/packager/src/net/rim/tumbler/config/WidgetConfig.java +++ b/packager/src/net/rim/tumbler/config/WidgetConfig.java @@ -35,6 +35,9 @@ public class WidgetConfig { private String _name; private String _version; + protected int _orientation; // Portrait 0, Landscape 1 + protected boolean _orientationDefined; + private String _loadingScreenColour; private String _backgroundImage; private String _foregroundImage; @@ -106,6 +109,9 @@ public WidgetConfig() { _aggressiveCacheAge= null; _maxCacheable = null; _maxCacheSize = null; + + _orientationDefined = false; + _orientation = -1; _runOnStartup=false; _allowInvokeParams=false; @@ -151,6 +157,14 @@ public String getDescription() { return _description; } + public int getOrientation() { + return _orientation; + } + + public boolean getOrientationDefined() { + return _orientationDefined; + } + public Vector getHoverIconSrc() { return _hoverIconSrc; } @@ -162,6 +176,11 @@ public Vector getIconSrc() { public void setContent(String content) { _content = content; } + + public void setOrientation(int value) { + _orientation = value; + _orientationDefined = true; + } public void setAuthor(String author) { _author = author; diff --git a/packager/src/net/rim/tumbler/serialize/WidgetConfig_v1Serializer.java b/packager/src/net/rim/tumbler/serialize/WidgetConfig_v1Serializer.java index 19a1fe5..0e21f66 100644 --- a/packager/src/net/rim/tumbler/serialize/WidgetConfig_v1Serializer.java +++ b/packager/src/net/rim/tumbler/serialize/WidgetConfig_v1Serializer.java @@ -135,6 +135,12 @@ public byte[] serialize() { if (_widgetConfig.getNavigationMode()) { buffer.append("_widgetNavigationMode = true;").append(NL_LVL_0); } + + // Set orientation + if (_widgetConfig.getOrientationDefined()) { + buffer.append("_orientationDefined = true;").append(NL_LVL_0); + buffer.append("_orientation = " + Integer.toString(_widgetConfig.getOrientation()) + ";").append(NL_LVL_0); + } // Add LoadingScreen configuration if (_widgetConfig.getFirstPageLoad()) { diff --git a/packager/src/net/rim/tumbler/xml/ConfigXMLParser.java b/packager/src/net/rim/tumbler/xml/ConfigXMLParser.java index 114be8c..f08eb09 100644 --- a/packager/src/net/rim/tumbler/xml/ConfigXMLParser.java +++ b/packager/src/net/rim/tumbler/xml/ConfigXMLParser.java @@ -102,6 +102,8 @@ private WidgetConfig parseDocument(Document dom, WidgetArchive archive) throws E processNavigationNode(node); } else if (node.getNodeName().equals("rim:cache")) { processCacheNode(node); + } else if (node.getNodeName().equals("rim:orientation")) { + processOrientationNode(node); } else if (node.getNodeName().equals("name")) { _widgetConfig.setName(getTextValue(node)); } else if (node.getNodeName().equals("description")) { @@ -601,6 +603,32 @@ private void processConnectionNode(Node connectionNode) throws Exception { _widgetConfig.setTransportOrder(transportArray); } } + + + // Processing for the node + private void processOrientationNode(Node orientationNode) throws Exception { + + // get mode + NamedNodeMap attrs = orientationNode.getAttributes(); + Node modeAttrNode = attrs.getNamedItem("mode"); + if (modeAttrNode != null) { + try{ + int orientation = -1; + if (modeAttrNode.getNodeValue().equalsIgnoreCase("portrait")) { + orientation = 0; + } else if (modeAttrNode.getNodeValue().equalsIgnoreCase("landscape")) { + orientation = 1; + } + // Only set the orientation if it was properly specified + if (orientation != -1) { + _widgetConfig.setOrientation(orientation); + } + }catch(Exception e){ + // Default values are used if an error happens + } + } + } + // Processing for the node private void processCacheNode(Node cacheNode) throws Exception { From 14e9b8ccd752bca4dc2b59d83da16a10b5c3499e Mon Sep 17 00:00:00 2001 From: David Meng Date: Tue, 6 Dec 2011 20:47:50 -0500 Subject: [PATCH 3/9] Fixed Mac dependency issue with path seperator char (mks2103444) --- packager/src/net/rim/tumbler/rapc/Rapc.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packager/src/net/rim/tumbler/rapc/Rapc.java b/packager/src/net/rim/tumbler/rapc/Rapc.java index b980f2c..810a7ce 100644 --- a/packager/src/net/rim/tumbler/rapc/Rapc.java +++ b/packager/src/net/rim/tumbler/rapc/Rapc.java @@ -343,8 +343,9 @@ public String generateParameters() { param.append( anImport ); - if( i < _imports.size() - 1 && _imports.size() != 1 ) - param.append( ";" ); + if( i < _imports.size() - 1 && _imports.size() != 1 ) { + param.append( File.pathSeparatorChar ); + } } param.append( "\" " ); } From fb015a148cfa7e8ad7a54805471864c570581362 Mon Sep 17 00:00:00 2001 From: James Choi Date: Fri, 9 Dec 2011 12:23:19 -0500 Subject: [PATCH 4/9] Fix for MKS2388157 whitelisting issue. --- .../web/widget/policy/WidgetPolicy.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/framework/src/blackberry/web/widget/policy/WidgetPolicy.java b/framework/src/blackberry/web/widget/policy/WidgetPolicy.java index 6c1f4a9..9c35abe 100644 --- a/framework/src/blackberry/web/widget/policy/WidgetPolicy.java +++ b/framework/src/blackberry/web/widget/policy/WidgetPolicy.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blackberry.web.widget.policy; +package blackberry.web.widget2743472eaea143320a3fee8b4e6f6epackage.policy; import java.util.Hashtable; @@ -21,7 +21,7 @@ import net.rim.device.api.io.URI; import net.rim.device.api.web.WidgetAccess; -import blackberry.web.widget.util.WidgetUtil; +import blackberry.web.widget2743472eaea143320a3fee8b4e6f6epackage.util.WidgetUtil; /** * @@ -80,10 +80,13 @@ public WidgetAccess getElement( String request, WidgetAccess[] accessList ) { if ( schemeString.equals( "local" ) && folderAccess == null ) { return _localAccess; } - + if(folderAccess != null) { fetchedAccess = folderAccess.getWidgetAccess( requestURI.getPath() + parseNull( requestURI.getQuery() ) ); } + if( !isMatch( fetchedAccess, requestURI ) ) { + fetchedAccess = folderAccess.getWidgetAccess( requestURI.getPath() + "*" ); + } boolean failedToFindAccess = false; // Make sure we've got the right one @@ -126,6 +129,10 @@ public WidgetAccess getElement( String request, WidgetAccess[] accessList ) { } private boolean isMatch( WidgetAccess access, URI toMatchURI ) { + if( access == null ) { + return false; + } + // Look for local first if( WidgetUtil.isLocalURI( toMatchURI ) && access.isLocal() ) { // local access always allowed @@ -172,6 +179,9 @@ else if( WidgetUtil.isDataURI( toMatchURI ) ) { // 5. Compare path+query String refPath = referenceURI.getPath() + parseNull( referenceURI.getQuery() ); String toMatchPath = toMatchURI.getPath() + parseNull( toMatchURI.getQuery() ); + if( refPath.endsWith( "*" ) ) { + refPath = refPath.substring( 0, refPath.length() - 1 ); + } if( !toMatchPath.startsWith( refPath ) ) { return false; } From 1dd9e83339f849f14cfec16dbaf427e1d7ce548c Mon Sep 17 00:00:00 2001 From: James Choi Date: Fri, 9 Dec 2011 13:09:42 -0500 Subject: [PATCH 5/9] Fixed package issue. --- framework/src/blackberry/web/widget/policy/WidgetPolicy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/blackberry/web/widget/policy/WidgetPolicy.java b/framework/src/blackberry/web/widget/policy/WidgetPolicy.java index 9c35abe..4df07ca 100644 --- a/framework/src/blackberry/web/widget/policy/WidgetPolicy.java +++ b/framework/src/blackberry/web/widget/policy/WidgetPolicy.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blackberry.web.widget2743472eaea143320a3fee8b4e6f6epackage.policy; +package blackberry.web.widget.policy; import java.util.Hashtable; @@ -21,7 +21,7 @@ import net.rim.device.api.io.URI; import net.rim.device.api.web.WidgetAccess; -import blackberry.web.widget2743472eaea143320a3fee8b4e6f6epackage.util.WidgetUtil; +import blackberry.web.widget.util.WidgetUtil; /** * From f0c25e47b45f6b81a5584a0829b26704a6a02348 Mon Sep 17 00:00:00 2001 From: David Meng Date: Mon, 12 Dec 2011 15:48:24 -0500 Subject: [PATCH 6/9] Integrated BBM change. --- api/bbm/lib/net_rim_bb_qm_platform.jar | Bin 68233 -> 70183 bytes .../BBMPlatformContextListenerImpl.java | 52 ++++++++++-- .../bbm/platform/BBMPlatformNamespace.java | 63 +++++++++++++- .../io/MessagingServiceListenerImpl.java | 19 +++++ .../bbm/platform/self/SelfNamespace.java | 2 +- .../self/profilebox/ProfileBoxNamespace.java | 7 +- .../platform/settings/SettingsNamespace.java | 39 +++++++++ .../bbm/platform/users/BBMPlatformUser.java | 22 +++-- .../bbm/platform/users/UsersNamespace.java | 80 ++++++++++++++++++ .../blackberry/bbm/platform/util/Util.java | 7 +- 10 files changed, 268 insertions(+), 23 deletions(-) create mode 100644 api/bbm/src/main/java/blackberry/bbm/platform/settings/SettingsNamespace.java diff --git a/api/bbm/lib/net_rim_bb_qm_platform.jar b/api/bbm/lib/net_rim_bb_qm_platform.jar index 1a173ba95d49cdc7672e23e227f6f561c7c82b5f..34543e7911f73cc90a53874478cd4b8d1af12d8e 100644 GIT binary patch delta 33645 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 delta 31866 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 4) { + options = args[3]; + } else { + options = null; + } + + // Throw exceptions for too long parameters + final int maxContentLength = 61124; + if(content.length() > maxContentLength) { + throw new IllegalArgumentException("content.length > " + maxContentLength); + } + final int maxDescLength = 128; + if(description.length() > maxDescLength) { + throw new IllegalArgumentException("description.length > " + maxDescLength); + } + + // Parse options object for title and contacts + final String title; + final ContactListProvider contacts; + if(options == null || options.equals(UNDEFINED)) { + title = null; + contacts = null; + } else { + // Title + final Scriptable optionsObj = (Scriptable) options; + final Object titleObj = optionsObj.getField("title"); + if(titleObj.equals(UNDEFINED)) { + title = null; + } else { + title = (String) titleObj; + } + + // Contacts + Object contactsObj = optionsObj.getField("users"); + if(contactsObj.equals(UNDEFINED)) { + contacts = null; + } else { + final BBMPlatformUser[] users = Util.scriptableUsersArrayToUserArray((Scriptable) contactsObj); + contacts = new Util.SimpleContactListProvider(users); + } + } + + // Call API + final BBMPlatformNamespace bbmpNpsc = BBMPlatformNamespace.getInstance(); + final MessagingService msgService = bbmpNpsc.getMessagingService(); + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + msgService.shareContent(description, new BBMPlatformData(content), contacts, title); + Util.dispatchCallback(onComplete, null); + } + }); + + return UNDEFINED; + } + + protected FunctionSignature[] getFunctionSignatures() { + FunctionSignature sig1 = new FunctionSignature(4); + sig1.addParam(String.class, true); + sig1.addParam(String.class, true); + sig1.addParam(ScriptableFunction.class, true); + sig1.addParam(Scriptable.class, false); + return new FunctionSignature[] { + sig1 + }; + } + } // ShareContentFunction private static String eventTypeToString(int eventType) { switch(eventType) { diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/util/Util.java b/api/bbm/src/main/java/blackberry/bbm/platform/util/Util.java index 6df0a7b..acc0502 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/util/Util.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/util/Util.java @@ -73,6 +73,11 @@ public static String bitmapToBase64Str(Bitmap bitmap) { } public static Bitmap requestBitmap(String uri) throws Exception { + byte[] bmpBytes = requestBitmapBytes(uri); + return Bitmap.createBitmapFromBytes(bmpBytes, 0, bmpBytes.length, 1); + } + + public static byte[] requestBitmapBytes(String uri) throws Exception { BrowserField browserField = (BrowserField) BBMPlatformExtension._browserField.get(); final BrowserFieldConfig bfConfig = browserField.getConfig(); final BrowserFieldController bfController = @@ -94,7 +99,7 @@ public static Bitmap requestBitmap(String uri) throws Exception { } catch(EOFException e) { } - return Bitmap.createBitmapFromBytes(bmpBytes.getArray(), 0, bmpBytes.size(), 1); + return bmpBytes.getArray(); } finally { try { ic.close(); From ed8a08f6bd945b5886a6582281bf5dcee83cc18d Mon Sep 17 00:00:00 2001 From: David Meng Date: Mon, 12 Dec 2011 16:14:39 -0500 Subject: [PATCH 7/9] Improvements to MemoryMaid watch dog --- .../main/java/blackberry/app/ExitFunction.java | 1 + .../src/blackberry/web/widget/MemoryMaid.java | 4 +++- framework/src/blackberry/web/widget/Widget.java | 7 +++---- .../src/blackberry/web/widget/WidgetScreen.java | 1 + .../web/widget/bf/WidgetRequestController.java | 16 ++++++++++------ 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/api/app/src/main/java/blackberry/app/ExitFunction.java b/api/app/src/main/java/blackberry/app/ExitFunction.java index c936460..3a21fa7 100644 --- a/api/app/src/main/java/blackberry/app/ExitFunction.java +++ b/api/app/src/main/java/blackberry/app/ExitFunction.java @@ -35,6 +35,7 @@ public Object execute( Object thiz, Object[] args ) { static class ExitRunner implements Runnable { public void run() { + System.gc(); // MemoryMaid System.exit( 0 ); } } diff --git a/framework/src/blackberry/web/widget/MemoryMaid.java b/framework/src/blackberry/web/widget/MemoryMaid.java index 5e8e834..fa6203a 100644 --- a/framework/src/blackberry/web/widget/MemoryMaid.java +++ b/framework/src/blackberry/web/widget/MemoryMaid.java @@ -23,7 +23,7 @@ */ public class MemoryMaid extends Thread { protected final static int LOWMEM_THRESHHOLD = 1024 * 1024 * 5; // 5Mb - protected final static float DEVIATION_THRESHHOLD = 0.05f; // 5% + protected final static float DEVIATION_THRESHHOLD = 0.10f; // 10% protected final static long GC_TIMEOUT = 25000; // Wait time after a gc. To avoid calling gc too much protected final static long SAMPLE_RATE = 5000; // How often to check memory @@ -110,4 +110,6 @@ public void stop() { public void flagGC() { _doGC = true; } + + } diff --git a/framework/src/blackberry/web/widget/Widget.java b/framework/src/blackberry/web/widget/Widget.java index adc0079..700008f 100644 --- a/framework/src/blackberry/web/widget/Widget.java +++ b/framework/src/blackberry/web/widget/Widget.java @@ -143,11 +143,10 @@ public static void main( String[] args ) { waitForStartupComplete(); } Widget widget = makeWidget( args, wConfig ); - MemoryMaid mm = MemoryMaid.getInstance(); - if( mm != null ) { - mm.start(); - } + widget.enterEventDispatcher(); + + MemoryMaid mm = MemoryMaid.getInstance(); if( mm != null ) { mm.stop(); } diff --git a/framework/src/blackberry/web/widget/WidgetScreen.java b/framework/src/blackberry/web/widget/WidgetScreen.java index 51f3e53..e97d7ab 100644 --- a/framework/src/blackberry/web/widget/WidgetScreen.java +++ b/framework/src/blackberry/web/widget/WidgetScreen.java @@ -48,6 +48,7 @@ public boolean onClose() { if( EventService.getInstance().fireEvent(ApplicationEventHandler.EVT_APP_EXIT, null, true) ) { return false; } + System.gc(); // MemoryMaid // Do not call the default onClose function so the save dialog is skipped. close(); return true; diff --git a/framework/src/blackberry/web/widget/bf/WidgetRequestController.java b/framework/src/blackberry/web/widget/bf/WidgetRequestController.java index 28a1f14..78b70d2 100644 --- a/framework/src/blackberry/web/widget/bf/WidgetRequestController.java +++ b/framework/src/blackberry/web/widget/bf/WidgetRequestController.java @@ -154,6 +154,16 @@ public void handleNavigationRequest( BrowserFieldRequest request ) throws Except throw e; } } + + MemoryMaid mm = MemoryMaid.getInstance(); + if( mm != null ) { + if( mm.isAlive() ) { + mm.flagGC(); + } else { + // Start the memory manager after our first page has been loaded + mm.start(); + } + } } /** @@ -161,12 +171,6 @@ public void handleNavigationRequest( BrowserFieldRequest request ) throws Except */ public InputConnection handleResourceRequest( BrowserFieldRequest request ) throws Exception { - // Clean up memory - MemoryMaid mm = MemoryMaid.getInstance(); - if( mm != null && mm.isAlive() ) { - mm.flagGC(); - } - if( this._browserField == null ) { return new HTTPResponseStatus( HTTPResponseStatus.SC_SERVER_ERROR, request ).getResponse(); } From 82bb027b22c2a789be5be9bc5927aa78e3dc3290 Mon Sep 17 00:00:00 2001 From: Daniel Mateescu Date: Tue, 13 Dec 2011 15:49:42 -0500 Subject: [PATCH 8/9] Folded down the Navigation Mode branch --- .../ui/dialog/ColorPickerAsyncFunction.java | 72 + .../ui/dialog/DateTimeAsyncFunction.java | 73 + .../blackberry/ui/dialog/DialogExtension.java | 3 +- .../blackberry/ui/dialog/DialogNamespace.java | 4 + .../ui/dialog/DialogRunnableFactory.java | 109 + .../blackberry/ui/dialog/IWebWorksDialog.java | 21 + .../ui/dialog/SelectAsyncFunction.java | 106 + .../ui/dialog/color/ColorPickerDialog.java | 694 ++++ .../ui/dialog/datetime/DateTimeDialog.java | 536 +++ .../blackberry/ui/dialog/select/GPATools.java | 137 + .../ui/dialog/select/SelectDialog.java | 351 ++ .../blackberry/ui/dialog/select/box-empty.png | Bin 0 -> 268 bytes .../blackberry/ui/dialog/select/chk-blue.png | Bin 0 -> 241 bytes .../blackberry/ui/dialog/select/chk-white.png | Bin 0 -> 422 bytes .../web/widget/bf/BrowserFieldScreen.java | 11 +- .../web/widget/bf/NavigationNamespace.java | 349 +- .../widget/bf/WidgetBrowserFieldListener.java | 91 +- .../web/widget/bf/WidgetFieldManager.java | 334 +- .../NavigationController.java | 324 +- .../NavigationExtension.java | 84 + .../NavigationMapUpdateDispatcherEvent.java | 260 -- .../NavigationUiDispatcherEvent.java | 699 +--- framework/src/js/navmode.js | 1 + framework/src/js/navmode_uncompressed.js | 1445 ++++++++ .../NavModeSmokeTestYUI2.0/StyleSheet.css | 35 + yui-tests/NavModeSmokeTestYUI2.0/basic.htm | 290 ++ yui-tests/NavModeSmokeTestYUI2.0/config.xml | 17 + yui-tests/NavModeSmokeTestYUI2.0/index.htm | 51 + yui-tests/NavModeSmokeTestYUI2.0/list.htm | 565 +++ .../navmode-browser-direction.js | 7 + .../NavModeSmokeTestYUI2.0/navmode-browser.js | 5 + yui-tests/NavModeSmokeTestYUI2.0/navmode.js | 1 + yui-tests/NavModeSmokeTestYUI2.0/readme.txt | 5 + yui-tests/NavModeSmokeTestYUI2.0/table.htm | 470 +++ yui-tests/NavModeSmokeTestYUI2.0/wheel.png | Bin 0 -> 7756 bytes .../yui2.9.0/assets/YUIexamples.js | 32 + .../yui2.9.0/assets/bg_hd.gif | Bin 0 -> 96 bytes .../yui2.9.0/assets/dpSyntaxHighlighter.css | 190 + .../yui2.9.0/assets/dpSyntaxHighlighter.js | 805 +++++ .../yui2.9.0/assets/example-hd-bg.gif | Bin 0 -> 1487 bytes .../yui2.9.0/assets/syntax.js | 134 + .../yui2.9.0/assets/yui-candy.jpg | Bin 0 -> 11389 bytes .../yui2.9.0/assets/yui.css | 416 +++ .../yui2.9.0/assets/yui.gif | Bin 0 -> 5901 bytes .../yui2.9.0/assets/yuiDistribution.css | 0 .../yui2.9.0/assets/yuilib.jpg | Bin 0 -> 9186 bytes .../build/assets/skins/sam/ajax-loader.gif | Bin 0 -> 3208 bytes .../yui2.9.0/build/assets/skins/sam/asc.gif | Bin 0 -> 177 bytes .../build/assets/skins/sam/autocomplete.css | 7 + .../build/assets/skins/sam/back-h.png | Bin 0 -> 334 bytes .../build/assets/skins/sam/back-v.png | Bin 0 -> 338 bytes .../yui2.9.0/build/assets/skins/sam/bar-h.png | Bin 0 -> 365 bytes .../yui2.9.0/build/assets/skins/sam/bar-v.png | Bin 0 -> 387 bytes .../yui2.9.0/build/assets/skins/sam/bg-h.gif | Bin 0 -> 212 bytes .../yui2.9.0/build/assets/skins/sam/bg-v.gif | Bin 0 -> 481 bytes .../build/assets/skins/sam/blankimage.png | Bin 0 -> 2314 bytes .../build/assets/skins/sam/button.css | 7 + .../build/assets/skins/sam/calendar.css | 8 + .../build/assets/skins/sam/carousel.css | 7 + .../build/assets/skins/sam/check0.gif | Bin 0 -> 608 bytes .../build/assets/skins/sam/check1.gif | Bin 0 -> 622 bytes .../build/assets/skins/sam/check2.gif | Bin 0 -> 609 bytes .../build/assets/skins/sam/colorpicker.css | 7 + .../build/assets/skins/sam/container.css | 7 + .../build/assets/skins/sam/datatable.css | 8 + .../yui2.9.0/build/assets/skins/sam/desc.gif | Bin 0 -> 177 bytes .../build/assets/skins/sam/dt-arrow-dn.png | Bin 0 -> 116 bytes .../build/assets/skins/sam/dt-arrow-up.png | Bin 0 -> 116 bytes .../build/assets/skins/sam/editor-knob.gif | Bin 0 -> 138 bytes .../assets/skins/sam/editor-sprite-active.gif | Bin 0 -> 5614 bytes .../build/assets/skins/sam/editor-sprite.gif | Bin 0 -> 5690 bytes .../build/assets/skins/sam/editor.css | 10 + .../assets/skins/sam/header_background.png | Bin 0 -> 158 bytes .../build/assets/skins/sam/hue_bg.png | Bin 0 -> 1120 bytes .../build/assets/skins/sam/imagecropper.css | 7 + .../build/assets/skins/sam/layout.css | 7 + .../build/assets/skins/sam/layout_sprite.png | Bin 0 -> 1409 bytes .../build/assets/skins/sam/loading.gif | Bin 0 -> 2673 bytes .../build/assets/skins/sam/logger.css | 7 + .../skins/sam/menu-button-arrow-disabled.png | Bin 0 -> 173 bytes .../assets/skins/sam/menu-button-arrow.png | Bin 0 -> 173 bytes .../yui2.9.0/build/assets/skins/sam/menu.css | 7 + .../sam/menubaritem_submenuindicator.png | Bin 0 -> 3618 bytes .../menubaritem_submenuindicator_disabled.png | Bin 0 -> 3618 bytes .../assets/skins/sam/menuitem_checkbox.png | Bin 0 -> 3625 bytes .../skins/sam/menuitem_checkbox_disabled.png | Bin 0 -> 3625 bytes .../skins/sam/menuitem_submenuindicator.png | Bin 0 -> 3617 bytes .../menuitem_submenuindicator_disabled.png | Bin 0 -> 3617 bytes .../build/assets/skins/sam/paginator.css | 7 + .../build/assets/skins/sam/picker_mask.png | Bin 0 -> 12174 bytes .../build/assets/skins/sam/profilerviewer.css | 7 + .../build/assets/skins/sam/progressbar.css | 7 + .../build/assets/skins/sam/resize.css | 7 + .../build/assets/skins/sam/simpleeditor.css | 10 + .../yui2.9.0/build/assets/skins/sam/skin.css | 35 + .../build/assets/skins/sam/slider.css | 7 + .../skins/sam/split-button-arrow-active.png | Bin 0 -> 280 bytes .../skins/sam/split-button-arrow-disabled.png | Bin 0 -> 185 bytes .../skins/sam/split-button-arrow-focus.png | Bin 0 -> 185 bytes .../skins/sam/split-button-arrow-hover.png | Bin 0 -> 185 bytes .../assets/skins/sam/split-button-arrow.png | Bin 0 -> 185 bytes .../build/assets/skins/sam/sprite.png | Bin 0 -> 3745 bytes .../build/assets/skins/sam/sprite.psd | Bin 0 -> 118162 bytes .../build/assets/skins/sam/tabview.css | 8 + .../assets/skins/sam/treeview-loading.gif | Bin 0 -> 2673 bytes .../assets/skins/sam/treeview-sprite.gif | Bin 0 -> 4326 bytes .../build/assets/skins/sam/treeview.css | 7 + .../yui2.9.0/build/assets/skins/sam/wait.gif | Bin 0 -> 1100 bytes .../build/assets/skins/sam/yuitest.css | 7 + .../yui2.9.0/build/base/base-min.css | 7 + .../yui2.9.0/build/base/base.css | 137 + .../yui2.9.0/build/dom/dom-debug.js | 1885 ++++++++++ .../yui2.9.0/build/dom/dom-min.js | 9 + .../yui2.9.0/build/dom/dom.js | 1846 ++++++++++ .../event-delegate/event-delegate-debug.js | 283 ++ .../event-delegate/event-delegate-min.js | 7 + .../build/event-delegate/event-delegate.js | 281 ++ .../event-mouseenter-debug.js | 218 ++ .../event-mouseenter/event-mouseenter-min.js | 7 + .../event-mouseenter/event-mouseenter.js | 218 ++ .../event-simulate/event-simulate-debug.js | 624 ++++ .../event-simulate/event-simulate-min.js | 7 + .../build/event-simulate/event-simulate.js | 624 ++++ .../yui2.9.0/build/event/event-debug.js | 2561 ++++++++++++++ .../yui2.9.0/build/event/event-min.js | 11 + .../yui2.9.0/build/event/event.js | 2537 ++++++++++++++ .../yui2.9.0/build/fonts/fonts-min.css | 7 + .../yui2.9.0/build/fonts/fonts.css | 55 + .../build/logger/assets/logger-core.css | 7 + .../yui2.9.0/build/logger/assets/logger.css | 57 + .../logger/assets/skins/sam/logger-skin.css | 55 + .../build/logger/assets/skins/sam/logger.css | 7 + .../yui2.9.0/build/logger/logger-debug.js | 2109 +++++++++++ .../yui2.9.0/build/logger/logger-min.js | 9 + .../yui2.9.0/build/logger/logger.js | 2109 +++++++++++ .../build/stylesheet/stylesheet-debug.js | 660 ++++ .../build/stylesheet/stylesheet-min.js | 7 + .../yui2.9.0/build/stylesheet/stylesheet.js | 656 ++++ .../yui2.9.0/build/utilities/utilities.js | 39 + .../build/yahoo-dom-event/yahoo-dom-event.js | 14 + .../yui2.9.0/build/yahoo/yahoo-debug.js | 1229 +++++++ .../yui2.9.0/build/yahoo/yahoo-min.js | 8 + .../yui2.9.0/build/yahoo/yahoo.js | 1229 +++++++ .../yuiloader-dom-event.js | 17 + .../yuitest/assets/skins/sam/yuitest-skin.css | 7 + .../yuitest/assets/skins/sam/yuitest.css | 7 + .../build/yuitest/assets/testlogger.css | 7 + .../build/yuitest/assets/yuitest-core.css | 7 + .../yui2.9.0/build/yuitest/yuitest-debug.js | 3120 +++++++++++++++++ .../yui2.9.0/build/yuitest/yuitest-min.js | 11 + .../yui2.9.0/build/yuitest/yuitest.js | 3120 +++++++++++++++++ .../build/yuitest/yuitest_core-debug.js | 2132 +++++++++++ .../build/yuitest/yuitest_core-min.js | 9 + .../yui2.9.0/build/yuitest/yuitest_core.js | 2132 +++++++++++ .../yui2.9.0/index.html | 174 + 155 files changed, 37673 insertions(+), 1507 deletions(-) create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/ColorPickerAsyncFunction.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/DateTimeAsyncFunction.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/DialogRunnableFactory.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/IWebWorksDialog.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/SelectAsyncFunction.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/color/ColorPickerDialog.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/datetime/DateTimeDialog.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/select/GPATools.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/select/SelectDialog.java create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/select/box-empty.png create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/select/chk-blue.png create mode 100644 api/dialog/src/main/java/blackberry/ui/dialog/select/chk-white.png create mode 100644 framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationExtension.java delete mode 100644 framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationMapUpdateDispatcherEvent.java create mode 100644 framework/src/js/navmode.js create mode 100644 framework/src/js/navmode_uncompressed.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/StyleSheet.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/basic.htm create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/config.xml create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/index.htm create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/list.htm create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/navmode-browser-direction.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/navmode-browser.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/navmode.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/readme.txt create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/table.htm create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/wheel.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/YUIexamples.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/bg_hd.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/example-hd-bg.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/syntax.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui-candy.jpg create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yuiDistribution.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yuilib.jpg create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/ajax-loader.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/asc.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/autocomplete.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-h.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-v.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-h.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-v.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-h.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-v.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/blankimage.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/button.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/calendar.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/carousel.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check0.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check1.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check2.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/colorpicker.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/container.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/datatable.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/desc.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-dn.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-up.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-knob.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite-active.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/header_background.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/hue_bg.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/imagecropper.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout_sprite.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/loading.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/logger.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow-disabled.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator_disabled.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox_disabled.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator_disabled.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/paginator.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/picker_mask.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/profilerviewer.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/progressbar.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/resize.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/simpleeditor.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/skin.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/slider.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-active.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-disabled.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-focus.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-hover.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.png create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.psd create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/tabview.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-loading.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-sprite.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/wait.gif create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/yuitest.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base-min.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event/event-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event/event-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event/event.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/fonts/fonts-min.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/fonts/fonts.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/logger/assets/logger-core.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/logger/assets/logger.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/logger/assets/skins/sam/logger-skin.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/logger/assets/skins/sam/logger.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/logger/logger-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/logger/logger-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/logger/logger.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/utilities/utilities.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yahoo-dom-event/yahoo-dom-event.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yahoo/yahoo-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yahoo/yahoo-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yahoo/yahoo.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuiloader-dom-event/yuiloader-dom-event.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/assets/skins/sam/yuitest-skin.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/assets/skins/sam/yuitest.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/assets/testlogger.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/assets/yuitest-core.css create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/yuitest-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/yuitest-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/yuitest.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/yuitest_core-debug.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/yuitest_core-min.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuitest/yuitest_core.js create mode 100644 yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/index.html diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/ColorPickerAsyncFunction.java b/api/dialog/src/main/java/blackberry/ui/dialog/ColorPickerAsyncFunction.java new file mode 100644 index 0000000..3c39ced --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/ColorPickerAsyncFunction.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package blackberry.ui.dialog; + +import net.rim.device.api.script.Scriptable; +import net.rim.device.api.script.ScriptableFunction; +import net.rim.device.api.ui.UiApplication; +import blackberry.core.FunctionSignature; +import blackberry.core.ScriptableFunctionBase; +import blackberry.ui.dialog.DialogRunnableFactory; + +/** + * Implementation of asynchronous color picker dialog + * + * @author jachoi + * + */ +public class ColorPickerAsyncFunction extends ScriptableFunctionBase { + + public static final String NAME = "colorPickerAsync"; + private final int HEX_BASE = 16; + + /** + * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[]) + */ + public Object execute( Object thiz, Object[] args ) throws Exception { + int initialColor = stringToColor( (String) args[ 0 ] ); + ScriptableFunction callback = (ScriptableFunction) args[ 1 ]; + + // create dialog + Runnable dr = DialogRunnableFactory.getColorPickerRunnable( initialColor, callback, thiz ); + + // queue + UiApplication.getUiApplication().invokeLater( dr ); + + // return value + return Scriptable.UNDEFINED; + } + + private int stringToColor(String color) { + if ( color.startsWith( "#" ) ) { + return Integer.parseInt( color.substring( 1 ), HEX_BASE ); + } + return Integer.parseInt( color, HEX_BASE ); + } + + /** + * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures() + */ + protected FunctionSignature[] getFunctionSignatures() { + FunctionSignature fs = new FunctionSignature( 2 ); + // initialColor + fs.addParam( String.class, true ); + // callback + fs.addParam( ScriptableFunction.class, true ); + + return new FunctionSignature[] { fs }; + } +} \ No newline at end of file diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/DateTimeAsyncFunction.java b/api/dialog/src/main/java/blackberry/ui/dialog/DateTimeAsyncFunction.java new file mode 100644 index 0000000..c728e05 --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/DateTimeAsyncFunction.java @@ -0,0 +1,73 @@ +/* +* Copyright 2010-2011 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package blackberry.ui.dialog; + +import blackberry.core.FunctionSignature; +import blackberry.core.ScriptableFunctionBase; + +import net.rim.device.api.script.Scriptable; +import net.rim.device.api.script.ScriptableFunction; +import net.rim.device.api.ui.UiApplication; + +import blackberry.ui.dialog.DialogRunnableFactory; + +public class DateTimeAsyncFunction extends ScriptableFunctionBase { + + public static final String NAME = "dateTimeAsync"; + + public static final int TYPE_DATE = 0; + public static final int TYPE_MONTH = 1; + public static final int TYPE_TIME = 2; + public static final int TYPE_DATETIME = 3; + public static final int TYPE_DATETIMELOCAL = 4; + + /** + * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[]) + */ + public Object execute(Object thiz, Object[] args) throws Exception { + String type = (String) args[0]; + Scriptable options = (Scriptable) args[1]; + ScriptableFunction callback = (ScriptableFunction) args[2] ; + + String value = (String)options.getField("value"); + String min = (String)options.getField("min"); + String max = (String)options.getField("max"); + + Runnable dr = DialogRunnableFactory.getDateTimeRunnable(type, value, min, max, callback, thiz); + + // queue + UiApplication.getUiApplication().invokeLater(dr); + + // return value + return Scriptable.UNDEFINED; + } + + /** + * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures() + */ + protected FunctionSignature[] getFunctionSignatures() { + FunctionSignature fs = new FunctionSignature(3); + // type + fs.addParam(String.class, true); + // options + fs.addParam(Scriptable.class, true); + //callback + fs.addParam(ScriptableFunction.class, true); + + return new FunctionSignature[] { fs }; + } +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/DialogExtension.java b/api/dialog/src/main/java/blackberry/ui/dialog/DialogExtension.java index 8a63bba..48abff4 100644 --- a/api/dialog/src/main/java/blackberry/ui/dialog/DialogExtension.java +++ b/api/dialog/src/main/java/blackberry/ui/dialog/DialogExtension.java @@ -31,7 +31,7 @@ public class DialogExtension implements WidgetExtension { public static final String FEATURE_DIALOG = "blackberry.ui.dialog"; - + /** * @see net.rim.device.api.web.WidgetExtension#register(WidgetConfig, BrowserField) */ @@ -44,6 +44,7 @@ public void register( WidgetConfig widgetConfig, BrowserField browserField ) { */ public void loadFeature( final String feature, final String version, final Document document, final ScriptEngine scriptengine ) throws Exception { + if( feature.equals( FEATURE_DIALOG ) ) { scriptengine.addExtension( feature, new DialogNamespace() ); } diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/DialogNamespace.java b/api/dialog/src/main/java/blackberry/ui/dialog/DialogNamespace.java index cbf405f..5eff632 100644 --- a/api/dialog/src/main/java/blackberry/ui/dialog/DialogNamespace.java +++ b/api/dialog/src/main/java/blackberry/ui/dialog/DialogNamespace.java @@ -17,6 +17,7 @@ import java.util.Hashtable; +import net.rim.device.api.script.ScriptEngine; import net.rim.device.api.script.Scriptable; import net.rim.device.api.ui.component.Dialog; @@ -52,6 +53,9 @@ public DialogNamespace() { _fields.put( StandardAskFunction.NAME, new StandardAskFunction() ); _fields.put( CustomAskFunction.NAME, new CustomAskFunction() ); + _fields.put( SelectAsyncFunction.NAME, new SelectAsyncFunction() ); + _fields.put( DateTimeAsyncFunction.NAME, new DateTimeAsyncFunction() ); + _fields.put( ColorPickerAsyncFunction.NAME, new ColorPickerAsyncFunction() ); _fields.put( D_OK, new Integer( Dialog.D_OK ) ); _fields.put( D_SAVE, new Integer( Dialog.D_SAVE ) ); _fields.put( D_DELETE, new Integer( Dialog.D_DELETE ) ); diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/DialogRunnableFactory.java b/api/dialog/src/main/java/blackberry/ui/dialog/DialogRunnableFactory.java new file mode 100644 index 0000000..c505e79 --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/DialogRunnableFactory.java @@ -0,0 +1,109 @@ +/* +* Copyright 2010-2011 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package blackberry.ui.dialog; + +import java.util.Vector; + +import net.rim.device.api.system.DeviceInfo; +import net.rim.device.api.script.ScriptableFunction; +import net.rim.device.api.script.ScriptableImpl; + +import blackberry.ui.dialog.datetime.DateTimeDialog; +import blackberry.ui.dialog.IWebWorksDialog; +import blackberry.ui.dialog.select.SelectDialog; +import blackberry.ui.dialog.color.ColorPickerDialog; + +public class DialogRunnableFactory { + + public static Runnable getDateTimeRunnable( String type, String value, String min, String max, ScriptableFunction callback, + Object thiz ) { + IWebWorksDialog d = new DateTimeDialog( type, value, min, max ); + return new DialogRunnable( d, callback, thiz ); + } + + public static Runnable getColorPickerRunnable( int initialColor, ScriptableFunction callback, Object thiz ) { + ColorPickerDialog d = new ColorPickerDialog( initialColor ); + return new DialogRunnable( d, callback, thiz ); + } + + public static Runnable getSelectRunnable(boolean allowMultiple, String[] labels, boolean[] enabled, boolean[] selected, int[] types, ScriptableFunction callback, Object thiz) { + IWebWorksDialog d = new SelectDialog(allowMultiple, labels, enabled, selected, types); + return new DialogRunnable(d, callback, thiz); + } + + private static class DialogRunnable implements Runnable { + private IWebWorksDialog _dialog; + private ScriptableFunction _callback; + private Object _context; + + /** + * Constructs a DialogRunnable object. + * + * @param dialog + * The dialog + * @param callback + * The callback + * @param context + * The context in which the callback executes (its "this" object) + */ + DialogRunnable( IWebWorksDialog dialog, ScriptableFunction callback, Object context ) { + _dialog = dialog; + _callback = callback; + _context = context; + } + + + /** + * Run the dialog. + * + * @see java.lang.Runnable#run() + */ + public void run() { + if(_dialog.show()) { + Object dialogValue = _dialog.getSelectedValue(); + Object retVal; + + boolean isFive = "5".equals(DeviceInfo.getSoftwareVersion().substring(0, 1)); + + //we'll accept Vector-type dialog return values for arrays + //otherwise get object's string as all ecma primitives will return a valid string representation of themselves + try { + if (dialogValue instanceof Vector) { + Vector v = (Vector)dialogValue; + if(isFive) { + ScriptableImpl s = new ScriptableImpl(); + for(int i = 0; i < v.size(); i++) { + s.putElement(i, v.elementAt(i)); + } + retVal = s; + } else { + Object[] s = new Object[v.size()]; + v.copyInto(s); + retVal = s; + } + } else { + retVal = dialogValue.toString(); + } + + _callback.invoke(null, new Object[] { retVal }); + } catch (Exception e) { + throw new RuntimeException("Invoke callback failed: " + e.getMessage()); + } + } + } + } +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/IWebWorksDialog.java b/api/dialog/src/main/java/blackberry/ui/dialog/IWebWorksDialog.java new file mode 100644 index 0000000..47e21b1 --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/IWebWorksDialog.java @@ -0,0 +1,21 @@ +/* +* Copyright 2010-2011 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package blackberry.ui.dialog; + +public interface IWebWorksDialog { + boolean show(); + Object getSelectedValue(); +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/SelectAsyncFunction.java b/api/dialog/src/main/java/blackberry/ui/dialog/SelectAsyncFunction.java new file mode 100644 index 0000000..c475b4f --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/SelectAsyncFunction.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package blackberry.ui.dialog; + +import net.rim.device.api.script.ScriptEngine; +import net.rim.device.api.script.Scriptable; +import net.rim.device.api.script.ScriptableFunction; +import net.rim.device.api.ui.UiApplication; +import blackberry.common.util.json4j.JSONArray; +import blackberry.core.FunctionSignature; +import blackberry.core.ScriptableFunctionBase; + +import blackberry.ui.dialog.DialogRunnableFactory; +import blackberry.ui.dialog.select.SelectDialog; + +/** + * Implementation of asynchronous selection dialog + * + * @author jachoi + * + */ +public class SelectAsyncFunction extends ScriptableFunctionBase { + + public static final String NAME = "selectAsync"; + + public static final int POPUP_ITEM_TYPE_OPTION = 0; + public static final int POPUP_ITEM_TYPE_GROUP = 1; + public static final int POPUP_ITEM_TYPE_SEPARATOR = 2; + + /** + * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[]) + */ + public Object execute( Object thiz, Object[] args ) throws Exception { + boolean allowMultiple = ( (Boolean) args[ 0 ] ).booleanValue(); + Scriptable choices = (Scriptable) args[ 1 ]; + ScriptableFunction callback = (ScriptableFunction) args[ 2 ]; + + int numChoices = choices.getElementCount(); + String[] labels = new String[ numChoices ]; + boolean[] enabled = new boolean[ numChoices ]; + boolean[] selected = new boolean[ numChoices ]; + int[] types = new int[ numChoices ]; + + populateChoiceStateArrays( choices, labels, enabled, selected, types, allowMultiple ); + + Runnable dr = DialogRunnableFactory.getSelectRunnable(allowMultiple, labels, enabled, selected, types, callback, thiz); + + // queue + UiApplication.getUiApplication().invokeLater(dr); + + // return value + return Scriptable.UNDEFINED; + } + + private void populateChoiceStateArrays( Scriptable fromScriptableChoices, String[] labels, boolean[] enabled, + boolean[] selected, int[] type, boolean allowMultiple ) { + try { + + boolean firstSelected = false; + boolean canSelect = true; + + for( int i = 0; i < fromScriptableChoices.getElementCount(); i++ ) { + Scriptable choice = (Scriptable) fromScriptableChoices.getElement( i ); + labels[ i ] = (String) choice.getField( "label" ); + enabled[ i ] = ( (Boolean) choice.getField( "enabled" ) ).booleanValue(); + + canSelect = allowMultiple || !firstSelected; + selected[ i ] = canSelect && enabled[ i ] && ( (Boolean) choice.getField( "selected" ) ).booleanValue(); + firstSelected = firstSelected || selected[ i ]; + + type[ i ] = ( (String) choice.getField( "type" ) ).equals( "group" ) ? POPUP_ITEM_TYPE_GROUP + : POPUP_ITEM_TYPE_OPTION; + } + } catch( Exception e ) { + throw new RuntimeException( e.getMessage() ); + } + } + + /** + * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures() + */ + protected FunctionSignature[] getFunctionSignatures() { + FunctionSignature fs = new FunctionSignature( 3 ); + // allowMultiple + fs.addParam( Boolean.class, true ); + // choices + fs.addParam( Scriptable.class, true ); + // callback + fs.addParam( ScriptableFunction.class, true ); + + return new FunctionSignature[] { fs }; + } +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/color/ColorPickerDialog.java b/api/dialog/src/main/java/blackberry/ui/dialog/color/ColorPickerDialog.java new file mode 100644 index 0000000..e7e4885 --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/color/ColorPickerDialog.java @@ -0,0 +1,694 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package blackberry.ui.dialog.color; + +import blackberry.ui.dialog.IWebWorksDialog; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Characters; +import net.rim.device.api.system.KeypadListener; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FieldChangeListener; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.TouchEvent; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.ButtonField; +import net.rim.device.api.ui.container.HorizontalFieldManager; +import net.rim.device.api.ui.container.PopupScreen; +import net.rim.device.api.ui.container.VerticalFieldManager; +import net.rim.device.api.util.MathUtilities; +import net.rim.device.api.util.NumberUtilities; + +/** + * Implementation of color picker dialog + * + * @author jachoi + * + */ +public class ColorPickerDialog extends Field implements IWebWorksDialog { + private int _selectedColor; + + public ColorPickerDialog( int initialColor ) { + super( Field.FOCUSABLE ); + _selectedColor = initialColor; + setPadding( 0, 0, 0, 0 ); + } + + public void setColor( int color ) { + _selectedColor = color; + } + + public int getPreferredWidth() { + return (int) Math.ceil( getFont().getHeight() * 1.618 ); + } + + public int getPreferredHeight() { + return getFont().getHeight(); + } + + protected void layout( int width, int height ) { + setExtent( getPreferredWidth(), getPreferredHeight() ); + } + + protected void paint( Graphics g ) { + int oldColor = g.getColor(); + try { + // Color + g.setColor( _selectedColor ); + g.fillRect( 0, 0, getWidth(), getHeight() ); + + // Border + g.setStrokeWidth( 1 ); + g.setColor( 0x000000 ); + g.drawRect( 0, 0, getWidth(), getHeight() ); + } finally { + g.setColor( oldColor ); + } + } + + protected void drawFocus( Graphics g, boolean on ) { + int oldColor = g.getColor(); + try { + g.setColor( 0x0000FF ); + g.drawRect( 0, 0, getWidth(), getHeight() ); + g.drawRect( 1, 1, getWidth() - 2, getHeight() - 2 ); + } finally { + g.setColor( oldColor ); + } + } + + private String colorToString( int color ) throws IllegalArgumentException { + StringBuffer sb = new StringBuffer( 7 ); + sb.append( "#" ); + NumberUtilities.appendNumber( sb, color & 0x00FFFFFF, 16, 6 ); + return sb.toString(); + } + + public boolean show() { + ColorPickerPopup picker = new ColorPickerPopup( _selectedColor ); + boolean result = picker.doModal(); + if( result ) { + _selectedColor = picker.getSelectedColor(); + invalidate(); + fieldChangeNotify( 0 ); + } + return result; + } + + public Object getSelectedValue() { + return colorToString( _selectedColor ); + } + + protected void paintBackground( Graphics g ) { + } + + public void setDirty( boolean dirty ) { + // We never want to be dirty or muddy + } + + public void setMuddy( boolean muddy ) { + // We never want to be dirty or muddy + } +} + +class BaseColorChooser extends Field { + private static final int FIELD_HEIGHT = 100; + private static final int FIELD_WIDTH = 40; + private static final int NUM_COLOURS = 7; + private static final int FRAME_THICKNESS = 2; + private static final int FRAME_HEIGHT = 10; + + private int _selectedColor; + + private int[] _xcoords; + private int[] _ycoords; + private int[] _colors; + private Bitmap _rainbow; + + private boolean _editing; + private int _y; + + BaseColorChooser() { + _y = FRAME_THICKNESS; + int yStep = FIELD_HEIGHT / ( NUM_COLOURS - 1 ); + + _xcoords = new int[] { 0, 0, 0, 0, 0, 0, 0, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, + FIELD_WIDTH }; + _ycoords = new int[] { 0, yStep, 2 * yStep, 3 * yStep, 4 * yStep, 5 * yStep, FIELD_HEIGHT, FIELD_HEIGHT, 5 * yStep, + 4 * yStep, 3 * yStep, 2 * yStep, yStep, 0 }; + _colors = new int[] { 0xff0000, 0xff00ff, 0x0000ff, 0x00ffff, 0x00ff00, 0xffff00, 0xff0000, 0xff0000, 0xffff00, 0x00ff00, + 0x00ffff, 0x0000ff, 0xff00ff, 0xff0000 }; + } + + public int getPreferredWidth() { + return FIELD_WIDTH; + } + + public int getPreferredHeight() { + return FIELD_HEIGHT; + } + + public int getSelectedColor() { + return _selectedColor; + } + + protected void layout( int width, int height ) { + width = getPreferredWidth(); + height = getPreferredHeight(); + + _rainbow = new Bitmap( width, height ); + Graphics rainbowGraphics = Graphics.create( _rainbow ); + rainbowGraphics.drawShadedFilledPath( _xcoords, _ycoords, null, _colors, null ); + + setExtent( width, height ); + } + + protected void paint( Graphics g ) { + int oldColor = g.getColor(); + try { + // Rainbow + g.drawBitmap( 0, 0, _rainbow.getWidth(), _rainbow.getHeight(), _rainbow, 0, 0 ); + + // Border + g.setColor( 0x000000 ); + g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT ); + if( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ) { + g.setColor( Color.WHITE ); + g.drawRect( 1, 1, FIELD_WIDTH - 2, FIELD_HEIGHT - 2 ); + } + + int frameY = _y - ( FRAME_HEIGHT >> 1 ); + + // draw the selector shadow + frameY++; + g.setColor( 0x000000 ); + g.fillRect( 0, frameY, FIELD_WIDTH, FRAME_THICKNESS ); // top + g.fillRect( 0, frameY + FRAME_HEIGHT - FRAME_THICKNESS, FIELD_WIDTH, FRAME_THICKNESS ); // bottom + frameY--; + + // draw selector foreground + g.setColor( Color.WHITE ); + g.fillRect( 0, frameY, FIELD_WIDTH, FRAME_THICKNESS ); // top + g.fillRect( 0, frameY + FRAME_HEIGHT - FRAME_THICKNESS, FIELD_WIDTH, FRAME_THICKNESS ); // bottom + g.fillRect( 0, frameY, FRAME_THICKNESS, FRAME_HEIGHT ); // left + g.fillRect( FIELD_WIDTH - FRAME_THICKNESS, frameY, FRAME_THICKNESS, FRAME_HEIGHT ); // right + } finally { + g.setColor( oldColor ); + } + } + + protected void paintBackground( Graphics g ) { + } + + protected void drawFocus( Graphics g, boolean on ) { + boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ); + try { + g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true ); + paint( g ); + } finally { + g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus ); + } + } + + public boolean isFocusable() { + return true; + } + + protected boolean keyChar( char key, int status, int time ) { + if( key == Characters.ESCAPE ) { + if( _editing ) { + return handleClick(); + } + } else if( key == Characters.ENTER ) { + return handleClick(); + } + return super.keyChar( key, status, time ); + } + + protected boolean navigationMovement( int dx, int dy, int status, int time ) { + return handleMovement( dx, dy ); + } + + protected boolean trackwheelRoll( int amount, int status, int time ) { + if( ( status & KeypadListener.STATUS_ALT ) != 0 ) { + return handleMovement( amount, 0 ); + } else { + return handleMovement( 0, amount ); + } + } + + private boolean handleMovement( int dx, int dy ) { + if( _editing ) { + int yMovement = dy * FIELD_HEIGHT / 20; + + _y = MathUtilities.clamp( 0, _y + yMovement, FIELD_HEIGHT - 1 ); + + int[] argbData = new int[ 1 ]; + _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 ); + _selectedColor = argbData[ 0 ]; + + invalidate( 0, 0, getWidth(), getHeight() ); + fieldChangeNotify( FieldChangeListener.PROGRAMMATIC ); + return true; + } + return false; + } + + protected boolean navigationClick( int status, int time ) { + return handleClick(); + } + + protected boolean trackwheelClick( int status, int time ) { + return handleClick(); + } + + private boolean handleClick() { + _editing = !_editing; + invalidate( 0, 0, getWidth(), getHeight() ); + return true; + } + + protected boolean touchEvent( TouchEvent message ) { + if( message == null ) { + throw new IllegalArgumentException( "ColorPickerField.touchEvent: TouchEvent message is null." ); + } + boolean isConsumed = false; + boolean isOutOfBounds = false; + int x = message.getX( 1 ); + int y = message.getY( 1 ); + int[] argbData = new int[ 1 ]; + // Check to ensure point is within this field + if( x <= 0 || y <= 0 || x > ( FIELD_WIDTH - 1 ) || y > ( FIELD_HEIGHT - 1 ) ) { + isOutOfBounds = true; + } + switch( message.getEvent() ) { + case TouchEvent.CLICK: + case TouchEvent.MOVE: + if( isOutOfBounds ) { + return true; // consume + } + _editing = true; // Pressed effect + // update color + _y = y; + _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 ); + _selectedColor = argbData[ 0 ]; + invalidate( 0, 0, getWidth(), getHeight() ); + fieldChangeNotify( FieldChangeListener.PROGRAMMATIC ); + isConsumed = true; + break; + case TouchEvent.UNCLICK: + if( isOutOfBounds ) { + _editing = false; // Reset presssed effect + return true; + } + + // A field change notification is only sent on UNCLICK to allow for recovery + // should the user cancel, i.e. click and move off the button + + _editing = false; // Reset pressed effect + + // update color + _y = y; + _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 ); + _selectedColor = argbData[ 0 ]; + invalidate( 0, 0, getWidth(), getHeight() ); + fieldChangeNotify( FieldChangeListener.PROGRAMMATIC ); + isConsumed = true; + + break; + } + return isConsumed; + } + +} + +class TintChooser extends Field { + private static final int FIELD_HEIGHT = 100; + private static final int FIELD_WIDTH = 100; + private static final int FRAME_SIZE = 10; + private static final int FRAME_THICKNESS = 2; + + private int _baseColor; + private int _selectedColor; + + private int[] _xcoords; + private int[] _ycoords; + private int[] _colors; + private Bitmap _backgroundBitmap; + + private boolean _editing; + + private int _x; + private int _y; + + TintChooser( int baseColor ) { + _baseColor = baseColor; + + // init cursor position + _x = FIELD_WIDTH - FRAME_SIZE / 2; + _y = FRAME_SIZE; + } + + public int getPreferredWidth() { + return FIELD_WIDTH; + } + + public int getPreferredHeight() { + return FIELD_HEIGHT; + } + + protected void layout( int width, int height ) { + width = getPreferredWidth(); + height = getPreferredHeight(); + + updateBitmap(); + + setExtent( width, height ); + } + + public void setColor( int newColor ) { + _baseColor = newColor; + updateBitmap(); + invalidate(); + } + + private void updateBitmap() { + int width = getPreferredWidth(); + int height = getPreferredHeight(); + + _xcoords = new int[] { 0, 0, width, width }; + _ycoords = new int[] { 0, height, height, 0 }; + _colors = new int[] { 0xFFFFFF, 0x000000, 0x000000, _baseColor }; + + // make new bitmap + _backgroundBitmap = new Bitmap( width, height );// Bitmap.ROWWISE_MONOCHROME , width, height);// Bitmap.DEFAULT_TYPE, + // width, height ); + Graphics bitmapGraphics = Graphics.create( _backgroundBitmap ); + bitmapGraphics.drawShadedFilledPath( _xcoords, _ycoords, null, _colors, null ); + + // Update selected color + int[] argbData = new int[ 1 ]; + _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 ); + _selectedColor = argbData[ 0 ]; + } + + protected void paint( Graphics g ) { + // Rainbow + g.drawBitmap( 0, 0, _backgroundBitmap.getWidth(), _backgroundBitmap.getHeight(), _backgroundBitmap, 0, 0 ); + + // Border + g.setColor( 0x000000 ); + g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT ); + if( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ) { + g.setColor( Color.WHITE ); + g.drawRect( 1, 1, FIELD_WIDTH - 2, FIELD_HEIGHT - 2 ); + } + + // Selector + int frameX = _x; + int frameY = _y; + + int oldColor = g.getColor(); + try { + // draw the selector + g.setColor( 0x000000 ); + frameX++; + frameY++; + + // Shadow Left, Right, Top, Bottom + g.fillRect( frameX - FRAME_SIZE / 2, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS ); + g.fillRect( frameX + FRAME_THICKNESS, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS ); + g.fillRect( frameX - FRAME_THICKNESS / 2, frameY - FRAME_SIZE / 2, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS ); + g.fillRect( frameX - FRAME_THICKNESS / 2, frameY + FRAME_THICKNESS, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS ); + + frameX--; + frameY--; + + g.setColor( Color.WHITE ); + // Left, Right, Top, Bottom + g.fillRect( frameX - FRAME_SIZE / 2, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS ); + g.fillRect( frameX + FRAME_THICKNESS, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS ); + g.fillRect( frameX - FRAME_THICKNESS / 2, frameY - FRAME_SIZE / 2, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS ); + g.fillRect( frameX - FRAME_THICKNESS / 2, frameY + FRAME_THICKNESS, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS ); + } finally { + g.setColor( oldColor ); + } + } + + protected void paintBackground( Graphics g ) { + } + + protected void drawFocus( Graphics g, boolean on ) { + boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ); + try { + g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true ); + paint( g ); + } finally { + g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus ); + } + } + + public boolean isFocusable() { + return true; + } + + protected boolean keyChar( char key, int status, int time ) { + if( key == Characters.ESCAPE ) { + if( _editing ) { + return handleClick(); + } + } else if( key == Characters.ENTER ) { + return handleClick(); + } + return super.keyChar( key, status, time ); + } + + protected boolean navigationMovement( int dx, int dy, int status, int time ) { + return handleMovement( dx, dy ); + } + + protected boolean trackwheelRoll( int amount, int status, int time ) { + if( ( status & KeypadListener.STATUS_ALT ) != 0 ) { + return handleMovement( amount, 0 ); + } else { + return handleMovement( 0, amount ); + } + } + + private boolean handleMovement( int dx, int dy ) { + if( _editing ) { + int xMovement = dx * FIELD_WIDTH / 20; + int yMovement = dy * FIELD_HEIGHT / 20; + + _x = MathUtilities.clamp( 0, _x + xMovement, FIELD_WIDTH - 1 ); + _y = MathUtilities.clamp( 0, _y + yMovement, FIELD_HEIGHT - 1 ); + + int[] argbData = new int[ 1 ]; + _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 ); + _selectedColor = argbData[ 0 ]; + + invalidate( 0, 0, getWidth(), getHeight() ); + fieldChangeNotify( FieldChangeListener.PROGRAMMATIC ); + return true; + } + return false; + } + + public int getSelectedColor() { + return _selectedColor; + } + + protected boolean navigationClick( int status, int time ) { + return handleClick(); + } + + protected boolean trackwheelClick( int status, int time ) { + return handleClick(); + } + + private boolean handleClick() { + _editing = !_editing; + invalidate( 0, 0, getWidth(), getHeight() ); + return true; + } + + protected boolean touchEvent( TouchEvent message ) { + if( message == null ) { + throw new IllegalArgumentException( "ButtonField.touchEvent: TouchEvent message is null." ); + } + boolean isConsumed = false; + boolean isOutOfBounds = false; + int x = message.getX( 1 ); + int y = message.getY( 1 ); + // Check to ensure point is within this field + if( x <= 0 || y <= 0 || x > ( FIELD_WIDTH - 1 ) || y > ( FIELD_HEIGHT - 1 ) ) { + isOutOfBounds = true; + } + int[] argbData = new int[ 1 ]; + switch( message.getEvent() ) { + case TouchEvent.CLICK: + case TouchEvent.MOVE: + if( isOutOfBounds ) { + return true; // consume + } + _editing = true; // Pressed effect + // update color + _x = x; + _y = y; + _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 ); + _selectedColor = argbData[ 0 ]; + invalidate( 0, 0, getWidth(), getHeight() ); + fieldChangeNotify( FieldChangeListener.PROGRAMMATIC ); + isConsumed = true; + break; + case TouchEvent.UNCLICK: + if( isOutOfBounds ) { + _editing = false; // Reset presssed effect + return true; + } + + // A field change notification is only sent on UNCLICK to allow for recovery + // should the user cancel, i.e. click and move off the button + + _editing = false; // Reset pressed effect + + // update state + _x = x; + _y = y; + _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 ); + _selectedColor = argbData[ 0 ]; + invalidate( 0, 0, getWidth(), getHeight() ); + fieldChangeNotify( FieldChangeListener.PROGRAMMATIC ); + isConsumed = true; + break; + } + return isConsumed; + } +} + +class ColorPreviewField extends Field { + private static final int FIELD_WIDTH = 40; + private static final int FIELD_HEIGHT = 30; + + private int _color; + + ColorPreviewField( int color ) { + _color = color; + } + + public int getPreferredWidth() { + return FIELD_WIDTH; + } + + public int getPreferredHeight() { + return FIELD_HEIGHT; + } + + protected void layout( int width, int height ) { + setExtent( getPreferredWidth(), getPreferredHeight() ); + } + + public void setColor( int color ) { + _color = color; + invalidate(); + } + + protected void paint( Graphics g ) { + int oldColor = g.getColor(); + try { + g.setColor( _color ); + g.fillRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT ); + + g.setColor( 0x000000 ); + g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT ); + } finally { + g.setColor( oldColor ); + } + } +} + +class ColorPickerPopup extends PopupScreen implements FieldChangeListener { + private BaseColorChooser _baseColorChooser; + private TintChooser _tintChooser; + private ColorPreviewField _previewField; + private ButtonField _okButton; + + private final int PADDING = 4; + private final int PADDING_BOTTOM = 39; + private final String OK = "OK"; + + public ColorPickerPopup( int initialColor ) { + super( new HorizontalFieldManager() ); + setPadding( PADDING, PADDING, PADDING, PADDING ); + _baseColorChooser = new BaseColorChooser(); + _baseColorChooser.setPadding( PADDING, PADDING, PADDING, PADDING ); + _baseColorChooser.setChangeListener( this ); + add( _baseColorChooser ); + + _tintChooser = new TintChooser( initialColor ); + _tintChooser.setPadding( PADDING, PADDING, PADDING, PADDING ); + _tintChooser.setChangeListener( this ); + add( _tintChooser ); + + VerticalFieldManager previewPane = new VerticalFieldManager(); + + _previewField = new ColorPreviewField( initialColor ); + _previewField.setPadding( PADDING, PADDING, PADDING + PADDING_BOTTOM, PADDING ); + previewPane.add( _previewField ); + + _okButton = new ButtonField( OK ); + _okButton.setChangeListener( this ); + previewPane.add( _okButton ); + + add( previewPane ); + } + + public void fieldChanged( Field field, int context ) { + field.setDirty( false ); // don't want the save dialog + if( field == _baseColorChooser ) { + // Get color from base chooser + // Update the tint chooser + // Update the result color + _tintChooser.setColor( _baseColorChooser.getSelectedColor() ); + _previewField.setColor( _tintChooser.getSelectedColor() ); + } else if( field == _tintChooser ) { + // Update the result color + _previewField.setColor( _tintChooser.getSelectedColor() ); + } else if( field == _okButton ) { + close(); + } + } + + protected boolean keyChar( char key, int status, int time ) { + if( key == Characters.ESCAPE ) { + close(); + return true; + } else if( key == Characters.ENTER ) { + close(); + return true; + } + return super.keyChar( key, status, time ); + } + + public int getSelectedColor() { + return _tintChooser.getSelectedColor(); + } + + public boolean doModal() { + UiApplication.getUiApplication().pushModalScreen( this ); + return true; + } +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/datetime/DateTimeDialog.java b/api/dialog/src/main/java/blackberry/ui/dialog/datetime/DateTimeDialog.java new file mode 100644 index 0000000..8650e02 --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/datetime/DateTimeDialog.java @@ -0,0 +1,536 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package blackberry.ui.dialog.datetime; + +import java.util.Calendar; +import java.util.Date; + +import net.rim.device.api.i18n.SimpleDateFormat; +import net.rim.device.api.ui.picker.DateTimePicker; + +import blackberry.ui.dialog.IWebWorksDialog; + +public class DateTimeDialog implements IWebWorksDialog { + + private Html5DateTimeObject _HTML5Calendar; + private DateTimePicker _dateTimePicker = null; + + public DateTimeDialog ( String type, String value, String min, String max ) { + if("date".equals(type)) { + _HTML5Calendar = new HTML5Date ( value ); + } else if("month".equals(type)) { + _HTML5Calendar = new HTML5Month( value ); + } else if("time".equals(type)) { + _HTML5Calendar = new HTML5Time( value ); + } else if("datetime".equals(type)) { + _HTML5Calendar = new HTML5DateTimeGlobal( value ); + } else if("local".equals(type)) { + _HTML5Calendar = new HTML5DateTimeLocal( value ); + } else { + throw new IllegalArgumentException("Invalid date type."); + } + + if ( _HTML5Calendar != null ) { + _HTML5Calendar.createDateTimePickerInstance(); + if ( min != null && min.length() != 0 ) { + _HTML5Calendar.setMin( min ); + } + if ( max != null && max.length() != 0 ) { + _HTML5Calendar.setMax( max ); + } + } + } + + public boolean show() { + return _dateTimePicker.doModal(); + } + + public Object getSelectedValue() { + SimpleDateFormat sdf = new SimpleDateFormat( _HTML5Calendar.getFormat().toString() ); + StringBuffer sb = sdf.format( _dateTimePicker.getDateTime(), new StringBuffer(16), null ); + + return sb.toString(); + } + + private static int parseInt( String s, int from, int to ) { + return net.rim.device.api.util.NumberUtilities.parseInt( s, from, to, 10 ); + } + + private static void setMonth( Calendar calendar, int year, int month ) { + calendar.set(Calendar.DAY_OF_MONTH, 0); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month); + } + + private static void setTime( Calendar calendar, int hour, int minutes, int seconds, int milli) { + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minutes); + calendar.set(Calendar.SECOND, seconds); + calendar.set(Calendar.MILLISECOND, milli); + } + + public class HTML5Month extends Html5DateTimeObject { + + public HTML5Month( String value ) { + if ( value != null && value.length() != 0 ) { + _html5Calendar = parse( value ); + } else { + _html5Calendar = Calendar.getInstance(); + } + } + + public HTML5Month( ) { + } + + public StringBuffer getFormat() { + if ( _format == null ) { + return new StringBuffer("yyyy-MM"); + } + return _format; + } + + public void createDateTimePickerInstance() { + if ( _html5Calendar == null ) { + _html5Calendar = Calendar.getInstance(); + } + _dateTimePicker = DateTimePicker.createInstance( _html5Calendar, getFormat().toString(), null ); + } + + public void setMin( String value ) { + Calendar minCalendar = parse( value ); + if ( minCalendar != null ) { + _dateTimePicker.setMinimumDate( minCalendar ); + } + } + + public void setMax( String value ) { + Calendar maxCalendar = parse( value ); + if ( maxCalendar != null ) { + _dateTimePicker.setMaximumDate( maxCalendar ); + } + } + + protected Calendar parse( String text ) { + try { + _format = new StringBuffer( 7 ); + int year = parseInt( text, 0, 4); + if( year <= 0 ) { throw new IllegalArgumentException(); } + + if ( text.length() < 5 || text.charAt(4) != '-' ) { throw new IllegalArgumentException(); } + + int month = parseInt( text, 5, 7 ); + if( month <= 0 || month > 12 ) { throw new IllegalArgumentException(); } + + Calendar calendar = getInstance(); + setMonth( calendar, year, month ); + _format.append( "yyyy-MM" ); + //clear time so that it doesn't interfere when setting setMinimumCalendar and setMaximumCalendar + setTime( calendar, 0, 0, 0, 0 ); + + return calendar; + } catch (Exception e) { + _format = null; + return null; + } + } + } + + public class HTML5Date extends Html5DateTimeObject { + private final int MONTH_LENGTH[] = {31,28,31,30,31,30,31,31,30,31,30,31}; + private final int LEAP_MONTH_LENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31}; + + public HTML5Date( String value ) { + if ( value != null && value.length() != 0 ) { + _html5Calendar = parse( value ); + } else { + _html5Calendar = Calendar.getInstance(); + } + } + + public HTML5Date() { + } + + public StringBuffer getFormat() { + if ( _format == null ) { + return new StringBuffer("yyyy-MM-dd"); + } + return _format; + } + + public void createDateTimePickerInstance() { + if ( _html5Calendar == null ) { + _html5Calendar = Calendar.getInstance(); + } + _dateTimePicker = DateTimePicker.createInstance( _html5Calendar, getFormat().toString(), null ); + } + + public void setMin( String value ) { + Calendar minCalendar = parse( value ); + if ( minCalendar != null ) { + _dateTimePicker.setMinimumDate( minCalendar ); + } + } + + public void setMax( String value ) { + Calendar maxCalendar = parse( value ); + if ( maxCalendar != null ) { + _dateTimePicker.setMaximumDate( maxCalendar ); + } + } + + protected Calendar parse( String text ) { + try { + int len = text.length(); + //parse month + HTML5Month month = new HTML5Month(); + Calendar calendar = month.parse( text ); + _format = month.getFormat(); + + if ( text.length() < 8 || text.charAt(7) != '-' ) { throw new IllegalArgumentException() ;} + + //parse day + int day = parseInt( text, 8, len ); + + if ( day < 1 || day > 31 ) { throw new IllegalArgumentException(); } + + //combine month and day + //calendar.set( Calendar.DAY_OF_MONTH, 0 ); + //((GregorianCalendar) calendar).roll( Calendar.DAY_OF_MONTH, day ); + + int mth = calendar.get(Calendar.MONTH); + System.out.println(Calendar.OCTOBER); + + int min = 0; + int max = monthLength(mth, calendar.get(Calendar.YEAR)); + // These are the standard roll instructions. These work for all + // simple cases, that is, cases in which the limits are fixed, such + // as the hour, the month, and the era. + int gap = max - min + 1; + int value = (day - min) % gap; + if (value < 0) value += gap; + value += min; + + calendar.set( Calendar.DAY_OF_MONTH, value ); + + _format.append("-dd"); + return calendar; + } catch (IllegalArgumentException e) { + _format = null; + return null; + } + } + + private final int monthLength(int month, int year) { + return isLeapYear(year) ? LEAP_MONTH_LENGTH[month] : MONTH_LENGTH[month]; + } + + private boolean isLeapYear(int year) { + return ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); + } + } + + public class HTML5Time extends Html5DateTimeObject { + + public HTML5Time( String value ) { + if ( value != null && value.length() != 0 ) { + _html5Calendar = parse( value ); + } else { + _html5Calendar = Calendar.getInstance(); + } + } + + public HTML5Time() { + } + + public StringBuffer getFormat() { + if ( _format == null ) { + return new StringBuffer("HH:mm:ss"); + } + return _format; + } + + public void createDateTimePickerInstance() { + if ( _html5Calendar == null ) { + _html5Calendar = Calendar.getInstance(); + } + _dateTimePicker = DateTimePicker.createInstance( _html5Calendar, null, getFormat().toString() ); + } + + public void setMin( String value ) { + Calendar minCalendar = parse ( value ); + if ( minCalendar != null ) { + _dateTimePicker.setMinimumDate( minCalendar ); + } + } + + public void setMax( String value ) { + Calendar maxCalendar = parse ( value ); + if ( maxCalendar != null ) { + _dateTimePicker.setMaximumDate( maxCalendar ); + } + } + + public void step( double value ) { + //DateTimePickerController only accepts Calendar.HOUR, + //or Calendar.MINUTE or Calendar.SECOND + //and the value comes in second increments + if (value >= 3600) { + _dateTimePicker.setIncrement( Calendar.HOUR, ((int) value)/3600 ); + } + else if (value >= 60) { + _dateTimePicker.setIncrement( Calendar.MINUTE, ((int) value)/60 ); + } + else { + _dateTimePicker.setIncrement( Calendar.SECOND, (int) value ); + } + } + + protected Calendar parse( String text ) { + try { + _format = new StringBuffer( 5 ); + int hour = parseInt( text, 0, 2 ); + if( hour < 0 || hour > 23 ) { throw new IllegalArgumentException(); } + + if ( text.length() < 3 || text.charAt(2) != ':' ) { throw new IllegalArgumentException(); } + + int minutes = parseInt( text, 3, 5 ); + if( minutes < 0 || minutes > 59 ) { throw new IllegalArgumentException(); } + + Calendar calendar = getInstance(); + int seconds = 0; + + _format.append("HH:mm"); + + if ( text.length() > 5 ) { //parse seconds + if ( text.charAt(5) != ':' ) { throw new IllegalArgumentException(); } + seconds = parseInt( text, 6, 8 ); + if( seconds < 0 || seconds > 59 ) { throw new IllegalArgumentException(); } + + _format.append(":ss"); + + //parse milliseconds + if ( text.length() > 8 && text.charAt(8) == '.' ) { + _format.append("."); + StringBuffer sb = new StringBuffer(); + for ( int i=9; i < text.length() ; i++ ) { + sb.append( text.charAt(i) ); + _format.append("S"); + } + int fracSeconds = parseInt( sb.toString(), 0, sb.toString().length() ); + setTime( calendar, hour, minutes, seconds, fracSeconds ); + + } else { //no milliseconds + setTime( calendar, hour, minutes, seconds, 0 ); + } + return calendar; + + } else { // no seconds + setTime( calendar, hour, minutes, 0, 0 ); + return calendar; + } + } catch (Exception e) { + _format = null; + return null; + } + } + } + + public class HTML5DateTimeLocal extends Html5DateTimeObject { + + public HTML5DateTimeLocal( String value ) { + if ( value != null && value.length() != 0 ) { + _html5Calendar = parse( value ); + } else { + _html5Calendar = Calendar.getInstance(); + } + } + + public HTML5DateTimeLocal() { + } + + public StringBuffer getFormat() { + if ( _format == null ) { + return new StringBuffer("yyyy-MM-dd'T'HH:mm"); + } + return _format; + } + + public void createDateTimePickerInstance() { + if ( _html5Calendar == null ) { + _html5Calendar = Calendar.getInstance(); + } + _dateTimePicker = DateTimePicker.createInstance( _html5Calendar ); + } + + public void setMin( String value ) { + Calendar minCalendar = parse ( value ); + if ( minCalendar != null ) { + _dateTimePicker.setMinimumDate( minCalendar ); + } + } + + public void setMax( String value ) { + Calendar maxCalendar = parse( value ); + if ( maxCalendar != null ) { + _dateTimePicker.setMaximumDate( maxCalendar ); + } + } + + protected Calendar parse( String text ) { + try { + int len = text.length(); + //parse date + HTML5Date date = new HTML5Date(); + Calendar calendar = date.parse( text.substring( 0, 10 ) ); + _format = date.getFormat(); + + //check for T + if ( text.indexOf( 'T',10 ) == -1 ) { throw new IllegalArgumentException(); } + + _format.append("'T'"); + + //parse time + HTML5Time htime = new HTML5Time(); + Calendar cTime = htime.parse( text.substring( 11, len ) ); + _format.append( htime.getFormat() ); + + //combine date and time + setTime( calendar, cTime.get(Calendar.HOUR_OF_DAY) , cTime.get(Calendar.MINUTE), cTime.get(Calendar.SECOND), cTime.get(Calendar.MILLISECOND) ); + return calendar; + + } catch (IllegalArgumentException e) { + _format = null; + return null; + } + } + } + + public class HTML5DateTimeGlobal extends Html5DateTimeObject { + + public HTML5DateTimeGlobal( String value ) { + if ( value != null && value.length() != 0 ) { + _html5Calendar = parse( value ); + } else { + _html5Calendar = Calendar.getInstance(); + } + } + + public HTML5DateTimeGlobal() { + } + + public StringBuffer getFormat() { + if ( _format == null ) { + return new StringBuffer("yyyy-MM-dd'T'HH:mm'Z'"); + } + return _format; + } + + public void setMin( String value ) { + Calendar minCalendar = parse ( value ); + if ( minCalendar != null ) { + _dateTimePicker.setMinimumDate( minCalendar ); + } + } + + public void setMax( String value ) { + Calendar maxCalendar = parse ( value ); + if ( maxCalendar != null ) { + _dateTimePicker.setMaximumDate( maxCalendar ); + } + } + + public void createDateTimePickerInstance() { + if ( _html5Calendar == null ) { + _html5Calendar = Calendar.getInstance(); + } + _dateTimePicker = DateTimePicker.createInstance( _html5Calendar ); + } + + protected Calendar parse ( String text ) { + try { + Calendar calendar; + int len = text.length(); + + if( text.charAt( len - 1 ) == 'Z' ) { + HTML5DateTimeLocal dtl = new HTML5DateTimeLocal(); + calendar = dtl.parse( text.substring( 0, len - 1 )); + _format = dtl.getFormat(); + _format.append("'Z'"); + return calendar; + } else { // Time zone adjustment + int signloc = text.indexOf( '-', 10 ); + if ( signloc == -1 ) { + signloc = text.indexOf( '+', 10 ); + } + + if ( signloc == -1 ) { throw new IllegalArgumentException(); } + String sign = text.substring ( signloc, signloc + 1 ); + + HTML5DateTimeLocal dtl = new HTML5DateTimeLocal(); + calendar = dtl.parse( text.substring( 0, signloc) ); + _format = dtl.getFormat(); + + HTML5Time htime = new HTML5Time(); + Calendar timeShift = htime.parse( text.substring( len - 5, len )); + _format.append( htime.getFormat() ); + + int hour = timeShift.get( Calendar.HOUR_OF_DAY ); + int minute = timeShift.get( Calendar.MINUTE ); + if ( sign.charAt(0) == '-' ) { + hour = timeShift.get( Calendar.HOUR_OF_DAY ) * -1; + minute = timeShift.get( Calendar.MINUTE ) * -1; + } + + long currentTime = calendar.getTime().getTime(); + long adjustedTime = currentTime + (hour * 60 * 60 * 1000 + minute * 60 * 1000); + + calendar.setTime(new Date(adjustedTime)); + + return calendar; + } + } catch (IllegalArgumentException e) { + _format = null; + return null; + } + } + } +} + +abstract class Html5DateTimeObject { + + protected Calendar _html5Calendar; + protected StringBuffer _format; + + Html5DateTimeObject() { + _html5Calendar = Calendar.getInstance(); + } + + public Calendar getInstance() { + if ( _html5Calendar == null ) { + _html5Calendar = Calendar.getInstance(); + } + return _html5Calendar; + } + + protected abstract Calendar parse( String text ); + public abstract void setMin( String value ); + public abstract void setMax( String value ); + public void step( double value ){ + } + public abstract StringBuffer getFormat(); + public abstract void createDateTimePickerInstance(); +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/select/GPATools.java b/api/dialog/src/main/java/blackberry/ui/dialog/select/GPATools.java new file mode 100644 index 0000000..6082928 --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/select/GPATools.java @@ -0,0 +1,137 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package blackberry.ui.dialog.select; + +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Graphics; +/** + * + * @author Patchou + * @version 1.01 + * + */ +public class GPATools +{ + /** + * Resizes a bitmap with an alpha channel (transparency) without the artifacts introduced + * by scaleInto(). + * + * @param bmpSrc Source Bitmap + * @param nWidth New Width + * @param nHeight New Height + * @param nFilterType Filter quality to use. Can be Bitmap.FILTER_LANCZOS, + * Bitmap.FILTER_BILINEAR or + * Bitmap.FILTER_BOX. + * @param nAspectRatio Specifies how the picture is resized. Can be + * Bitmap.SCALE_TO_FIT, + * Bitmap.SCALE_TO_FILL or + * Bitmap.SCALE_STRETCH. + * @return The resized Bitmap in a new object. + */ + public static Bitmap ResizeTransparentBitmap(Bitmap bmpSrc, int nWidth, int nHeight, int nFilterType, int nAspectRatio) + { + if(bmpSrc == null) + return null; + + //Get the original dimensions of the bitmap + int nOriginWidth = bmpSrc.getWidth(); + int nOriginHeight = bmpSrc.getHeight(); + if(nWidth == nOriginWidth && nHeight == nOriginHeight) + return bmpSrc; + + //Prepare a drawing bitmap and graphic object + Bitmap bmpOrigin = new Bitmap(nOriginWidth, nOriginHeight); + Graphics graph = Graphics.create(bmpOrigin); + + //Create a line of transparent pixels for later use + int[] aEmptyLine = new int[nWidth]; + for(int x = 0; x < nWidth; x++) + aEmptyLine[x] = 0x00000000; + //Create two scaled bitmaps + Bitmap[] bmpScaled = new Bitmap[2]; + for(int i = 0; i < 2; i++) + { + //Draw the bitmap on a white background first, then on a black background + graph.setColor((i == 0) ? Color.WHITE : Color.BLACK); + graph.fillRect(0, 0, nOriginWidth, nOriginHeight); + graph.drawBitmap(0, 0, nOriginWidth, nOriginHeight, bmpSrc, 0, 0); + + //Create a new bitmap with the desired size + bmpScaled[i] = new Bitmap(nWidth, nHeight); + if(nAspectRatio == Bitmap.SCALE_TO_FIT) + { + //Set the alpha channel of all pixels to 0 to ensure transparency is + //applied around the picture, if needed by the transformation + for(int y = 0; y < nHeight; y++) + bmpScaled[i].setARGB(aEmptyLine, 0, nWidth, 0, y, nWidth, 1); + } + + //Scale the bitmap + bmpOrigin.scaleInto(bmpScaled[i], nFilterType, nAspectRatio); + } + + //Prepare objects for final iteration + Bitmap bmpFinal = bmpScaled[0]; + int[][] aPixelLine = new int[2][nWidth]; + + //Iterate every line of the two scaled bitmaps + for(int y = 0; y < nHeight; y++) + { + bmpScaled[0].getARGB(aPixelLine[0], 0, nWidth, 0, y, nWidth, 1); + bmpScaled[1].getARGB(aPixelLine[1], 0, nWidth, 0, y, nWidth, 1); + + //Check every pixel one by one + for(int x = 0; x < nWidth; x++) + { + //If the pixel was untouched (alpha channel still at 0), keep it transparent + if(((aPixelLine[0][x] >> 24) & 0xff) == 0) + aPixelLine[0][x] = 0x00000000; + else + { + //Compute the alpha value based on the difference of intensity + //in the red channel + int nAlpha = ((aPixelLine[1][x] >> 16) & 0xff) - + ((aPixelLine[0][x] >> 16) & 0xff) + 255; + if(nAlpha == 0) + aPixelLine[0][x] = 0x00000000; //Completely transparent + else if(nAlpha >= 255) + aPixelLine[0][x] |= 0xff000000; //Completely opaque + else + { + //Compute the value of the each channel one by one + int nRed = ((aPixelLine[0][x] >> 16 ) & 0xff); + int nGreen = ((aPixelLine[0][x] >> 8 ) & 0xff); + int nBlue = (aPixelLine[0][x] & 0xff); + + nRed = (int)(255 + (255.0 * ((double)(nRed-255)/(double)nAlpha))); + nGreen = (int)(255 + (255.0 * ((double)(nGreen-255)/(double)nAlpha))); + nBlue = (int)(255 + (255.0 * ((double)(nBlue-255)/(double)nAlpha))); + + if(nRed < 0) nRed = 0; + if(nGreen < 0) nGreen = 0; + if(nBlue < 0) nBlue = 0; + aPixelLine[0][x] = nBlue | (nGreen<<8) | (nRed<<16) | (nAlpha<<24); + } + } + } + + //Change the pixels of this line to their final value + bmpFinal.setARGB(aPixelLine[0], 0, nWidth, 0, y, nWidth, 1); + } + return bmpFinal; + } +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/select/SelectDialog.java b/api/dialog/src/main/java/blackberry/ui/dialog/select/SelectDialog.java new file mode 100644 index 0000000..4a00469 --- /dev/null +++ b/api/dialog/src/main/java/blackberry/ui/dialog/select/SelectDialog.java @@ -0,0 +1,351 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package blackberry.ui.dialog.select; + +import java.util.Vector; + +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Characters; +import net.rim.device.api.system.Display; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.DrawStyle; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FieldChangeListener; +import net.rim.device.api.ui.Font; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.TouchEvent; +import net.rim.device.api.ui.TouchGesture; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.ButtonField; +import net.rim.device.api.ui.component.ListField; +import net.rim.device.api.ui.component.ListFieldCallback; +import net.rim.device.api.ui.component.SeparatorField; +import net.rim.device.api.ui.container.PopupScreen; +import net.rim.device.api.ui.container.VerticalFieldManager; + +import blackberry.ui.dialog.SelectAsyncFunction; +import blackberry.ui.dialog.IWebWorksDialog; + +/** + * Implementation of selection dialog + * + * @author jachoi + * + */ +public class SelectDialog extends PopupScreen implements FieldChangeListener, IWebWorksDialog { + + private ButtonField _doneButton; + private VerticalFieldManager _vfm; + private SelectListField _list; + + private ListItem[] _listItems; + private Vector _response; + + private int _choiceLength; + private boolean _allowMultiple; + private int _selectedIndex; + + private boolean _dialogAccepted; + + public SelectDialog( boolean allowMultiple, String[] labels, boolean[] enableds, boolean[] selecteds, int[] types ) { + super( new VerticalFieldManager( VERTICAL_SCROLL | VERTICAL_SCROLLBAR ) ); + _choiceLength = labels.length; + _allowMultiple = allowMultiple; + _response = new Vector(); + _selectedIndex = -1; + _dialogAccepted = false; + + _listItems = new ListItem[ _choiceLength ]; + int indexAssignment = 0; + for( int index = 0; index < _choiceLength; index++ ) { + if( _selectedIndex == -1 && selecteds[ index ] && enableds[ index ] ) { + _selectedIndex = index; + } + if( types[ index ] == SelectAsyncFunction.POPUP_ITEM_TYPE_OPTION ) { + _listItems[ index ] = new ListItem( labels[ index ], enableds[ index ], selecteds[ index ], types[ index ], + indexAssignment ); + indexAssignment++; + } else { + _listItems[ index ] = new ListItem( labels[ index ], enableds[ index ], selecteds[ index ], types[ index ], -1 ); + } + } + + _list = new SelectListField(); + _list.setChangeListener( this ); + _vfm = new VerticalFieldManager( NO_HORIZONTAL_SCROLL | NO_HORIZONTAL_SCROLLBAR | VERTICAL_SCROLL | VERTICAL_SCROLLBAR ); + _vfm.add( _list ); + add( _vfm ); + + if( _allowMultiple ) { + _doneButton = new ButtonField( "Done", Field.FIELD_HCENTER ); + _doneButton.setChangeListener( this ); + + add( new SeparatorField() ); + add( _doneButton ); + } + } + + public boolean show() { + UiApplication.getUiApplication().pushModalScreen( this ); + return _dialogAccepted; + } + + private void close(boolean changeAccepted) { + _dialogAccepted = changeAccepted; + super.close(); + } + + public Object getSelectedValue() { + return _response; + } + + public void fieldChanged( Field field, int arg1 ) { + for( int index = 0; index < _listItems.length; index++ ) { + if( _listItems[ index ].isSelected() ) { + _response.addElement( new Integer( index ) ); + } + } + + close( true ); + } + + private void updateCurrentSelection( char keyChar ) { + // Ensure we were passed a valid key to locate. + if( keyChar == '\u0000' ) { + return; + } else { + int lastFieldIndex = _choiceLength - 1; + int indexWithFocus = _list.getSelectedIndex(); + + for( int i = indexWithFocus == lastFieldIndex ? 0 : indexWithFocus + 1; i != indexWithFocus; i++ ) { + String label = _listItems[ i ].toString(); + if( label.indexOf( keyChar ) == 0 || label.substring( 0, 1 ).toLowerCase().indexOf( keyChar ) == 0 ) { + _list.setSelectedIndex( i ); + break; + } + // Wrap around. + if( i == _choiceLength - 1 ) { + i = -1; + } + } + } + } + + /* @Override */ + protected boolean touchEvent( TouchEvent message ) { + switch( message.getEvent() ) { + case TouchEvent.GESTURE: + if( _allowMultiple && message.getGesture().getEvent() == TouchGesture.NAVIGATION_SWIPE ) { + int swipeDirection = message.getGesture().getSwipeDirection(); + Field field = getLeafFieldWithFocus(); + if( field instanceof ListField ) { + switch( swipeDirection ) { + case TouchGesture.SWIPE_EAST: + _doneButton.setFocus(); + return true; + } + } else if( field instanceof ButtonField ) { + switch( swipeDirection ) { + case TouchGesture.SWIPE_NORTH: + case TouchGesture.SWIPE_WEST: + _list.setFocus(); + _list.setSelectedIndex( _list._previousSelected ); + return true; + } + } + } + } + return super.touchEvent( message ); + } + + /* @Override */ + protected boolean keyChar( char c, int status, int time ) { + switch( c ) { + case Characters.ENTER: + Field field = getLeafFieldWithFocus(); + if( field == _doneButton ) { + fieldChanged( _doneButton, -1 ); + } else { + _list.invokeAction( Field.ACTION_INVOKE ); + } + return true; + case Characters.ESCAPE: + close(false); + return true; + default: + updateCurrentSelection( c ); + break; + } + return super.keyChar( c, status, time ); + } + + private final class SelectListField extends ListField implements ListFieldCallback { + private static final int PADDING = 10; + public int _previousSelected = -1; + + SelectListField() { + setCallback( this ); + setSize( _choiceLength ); + setSelectedIndex( _selectedIndex ); + } + + protected void onUnfocus() { + _previousSelected = this.getSelectedIndex(); + super.onUnfocus(); + } + + protected boolean invokeAction( int action ) { + if( action == Field.ACTION_INVOKE ) { + int selectedIndex = getSelectedIndex(); + ListItem listItem = (ListItem) get( this, selectedIndex ); + + if( !listItem.isEnabled() || listItem.getType() == SelectAsyncFunction.POPUP_ITEM_TYPE_GROUP + || listItem.getType() == SelectAsyncFunction.POPUP_ITEM_TYPE_SEPARATOR ) { + return true; + } + + if( !_allowMultiple ) { + if( _selectedIndex != -1 ) { + _listItems[ _selectedIndex ].setSelected( false ); + } + listItem.setSelected( true ); + _selectedIndex = selectedIndex; + fieldChanged( null, -1 ); + } else { + listItem.setSelected( !listItem.isSelected() ); + invalidate(); + } + return true; + } + return false; + } + + public void drawListRow( ListField listField, Graphics graphics, int index, int y, int w ) { + Object obj = get( listField, index ); + if( obj instanceof ListItem ) { + paintListItem( (ListItem) obj, listField, graphics, index, y, w ); + } + } + + private void paintListItem( ListItem listItem, ListField listField, Graphics graphics, int index, int y, int width ) { + String text = listItem.toString().trim(); + + int type = listItem.getType(); + Font font = graphics.getFont(); + final int checkboxSize = font.getHeight() - 6; + final int textStart = PADDING + checkboxSize + 10; + + Bitmap checkWhite = GPATools.ResizeTransparentBitmap( Bitmap.getBitmapResource( "chk-white.png" ), checkboxSize, + checkboxSize, Bitmap.FILTER_BOX, Bitmap.SCALE_TO_FILL ); + Bitmap checkBlue = GPATools.ResizeTransparentBitmap( Bitmap.getBitmapResource( "chk-blue.png" ), checkboxSize, + checkboxSize, Bitmap.FILTER_BILINEAR, Bitmap.SCALE_TO_FILL ); + Bitmap boxEmpty = GPATools.ResizeTransparentBitmap( Bitmap.getBitmapResource( "box-empty.png" ), checkboxSize, + checkboxSize, Bitmap.FILTER_BILINEAR, Bitmap.SCALE_TO_FILL ); + + switch( type ) { + case SelectAsyncFunction.POPUP_ITEM_TYPE_SEPARATOR: + graphics.setColor( Color.GRAY ); + int lineY = y + listField.getRowHeight() / 3; + graphics.drawLine( PADDING, lineY, width - PADDING, lineY ); + break; + case SelectAsyncFunction.POPUP_ITEM_TYPE_GROUP: + graphics.setColor( Color.GRAY ); + font = font.derive( Font.BOLD ); + graphics.setFont( font ); + graphics.drawText( text, PADDING, y, DrawStyle.ELLIPSIS, width - PADDING ); // no fudge added to y coordinate + break; + case SelectAsyncFunction.POPUP_ITEM_TYPE_OPTION: + boolean enabled = listItem.isEnabled(); + if( !enabled ) { + graphics.setColor( Color.GRAY ); + } + + if( _allowMultiple ) { + graphics.drawBitmap( PADDING, y + 3, checkboxSize, checkboxSize, boxEmpty, 0, 0 ); + } + + if( listItem.isSelected() ) { + if( _allowMultiple ) { + graphics.drawBitmap( PADDING, y + 3, checkboxSize, checkboxSize, checkBlue, 0, 0 ); + } else { + graphics.drawBitmap( PADDING, y + 3, checkboxSize, checkboxSize, checkWhite, 0, 0 ); + } + } + + graphics.drawText( text, textStart, y, DrawStyle.ELLIPSIS, width - textStart ); // no fudge added to y + // coordinate + break; + default: + } + } + + public Object get( ListField list, int index ) { + return _listItems[ index ]; + } + + public int getPreferredWidth( ListField arg0 ) { + return Display.getWidth(); + } + + public int indexOfList( ListField arg0, String arg1, int arg2 ) { + return -1; + } + } + + /* + * Store choice information. + */ + private static final class ListItem { + private final String _label; + private boolean _selected; + private boolean _enabled; + private int _type; + private int _index; + + public ListItem( String label, boolean enabled, boolean selected, int type, int index ) { + _label = label; + _selected = selected; + _enabled = enabled; + _type = type; + _index = index; + } + + /* @Override */ + public String toString() { + return _label; + } + + public void setSelected( boolean value ) { + _selected = value; + } + + public boolean isSelected() { + return _selected; + } + + public boolean isEnabled() { + return _enabled; + } + + public int getType() { + return _type; + } + + public int getIndex() { + return _index; + } + } +} diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/select/box-empty.png b/api/dialog/src/main/java/blackberry/ui/dialog/select/box-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..16f0b0d14fcb500ca2e39a230a80639b1569b7bf GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1SBVD?P>#3Y)RhkEG(ocgzvb3$F%5m{W7e#KPxJQxNpnTk~qOA zv$UG|Z3*jHm;XzazkRtW)OaoLO4c>+oMiOh7wrGc)U)^r@43&ro9dE|xPv_9>FVdQ I&MBb@0PebGOaK4? literal 0 HcmV?d00001 diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/select/chk-blue.png b/api/dialog/src/main/java/blackberry/ui/dialog/select/chk-blue.png new file mode 100644 index 0000000000000000000000000000000000000000..6d2a1d0e8c2e15cc2669595ad72b48afe9183a3b GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa#^NA%Cx&(BWL^R}Y)RhkE)4%c zaKYZ?lYt_f1s;*bKrKf=m~pB$pEOXAy~NYkmHjrisGzu_25H|8(z?)N;t(rK2L=Z)W|bIRH$eMsYpJ6C_9*O4JXe(8_Mwwh@# zjwv`NMXQIY->MUAU=CF+bMDjI@Ui&Yg|Y~dsf)Q)D%VVzz{SB(k>}Uc=CH?6Qb%?X dS6$prS$96u|KESV^Z{DV;OXk;vd$@?2>^rtQknn& literal 0 HcmV?d00001 diff --git a/api/dialog/src/main/java/blackberry/ui/dialog/select/chk-white.png b/api/dialog/src/main/java/blackberry/ui/dialog/select/chk-white.png new file mode 100644 index 0000000000000000000000000000000000000000..531c8df3eb8aaf18f74954ffe270b8a060ba4b6a GIT binary patch literal 422 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa#^NA%Cx&(BWL^R}Y)RhkE)4%c zaKYZ?lYt_f1s;*bKrKf=m~pB$pEOXAy~NYkmHjriD8DwFLFxI4KvUE_T^vI+&hMRc z){7}oq-}mam-tStl9~3CGZ+8OTP3~HyTgk|<&cq<(yk7%i&{$Tm)#Ec%(>X~N^Vc@ zksQN#?d2|-*%xo_v)S`}&wIgx6OP5Z{nUN%wW45W3=dC##qYL1`vTW^MQ)3F-(G9U zr8r~WtS9fbX)wO}T2;Tg?YQ%c>Cc4{w5N()y`|i2Z|UoD=*fB`p#~?&pLuO( zGaoqd(n##;jM;M|HK%i(^9}pD@OMvwhjXBanD{f}^yTW_@kc9^G<{Zg<=);ae_&hg zym|4{%FDjHMtkHfJ5qb}4JYH=l~S$JQtNpe8@e)U@4wyuH>=u?VMTC)PR(E6f51Rw N@O1TaS?83{1OUy0tyKU3 literal 0 HcmV?d00001 diff --git a/framework/src/blackberry/web/widget/bf/BrowserFieldScreen.java b/framework/src/blackberry/web/widget/bf/BrowserFieldScreen.java index 3dc653c..7411165 100644 --- a/framework/src/blackberry/web/widget/bf/BrowserFieldScreen.java +++ b/framework/src/blackberry/web/widget/bf/BrowserFieldScreen.java @@ -35,6 +35,7 @@ import blackberry.web.widget.Widget; import blackberry.web.widget.WidgetScreen; import blackberry.web.widget.bf.navigationcontroller.NavigationController; +import blackberry.web.widget.bf.navigationcontroller.NavigationExtension; import blackberry.web.widget.caching.CacheManager; import blackberry.web.widget.caching.WidgetCacheNamespace; import blackberry.web.widget.device.DeviceInfo; @@ -61,8 +62,9 @@ public final class BrowserFieldScreen extends WidgetScreen { private static BrowserField _browserFieldReference; + private NavigationExtension _navigationJS; private NavigationController _navigationController; - private NavigationNamespace _navigationExtension; + private NavigationNamespace _navigationExtension; private PageManager _pageManager; @@ -184,7 +186,8 @@ private void initialize() { | Manager.HORIZONTAL_SCROLLBAR ); // navController depends on navExtension. Initialize navExtension first - _navigationExtension = new NavigationNamespace( this ); + _navigationJS = new NavigationExtension(); + _navigationExtension = new NavigationNamespace( this, (WidgetFieldManager) _manager ); _navigationController = new NavigationController( this ); } else { _manager = new VerticalFieldManager( Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR | Manager.HORIZONTAL_SCROLL @@ -312,6 +315,10 @@ public GearsHTML5Extension getHTML5Extension() { return _HTML5ToGearsExtension; } + public NavigationExtension getNavigationJS() { + return _navigationJS; + } + public NavigationNamespace getNavigationExtension() { return _navigationExtension; } diff --git a/framework/src/blackberry/web/widget/bf/NavigationNamespace.java b/framework/src/blackberry/web/widget/bf/NavigationNamespace.java index 56ae247..a8f4e21 100644 --- a/framework/src/blackberry/web/widget/bf/NavigationNamespace.java +++ b/framework/src/blackberry/web/widget/bf/NavigationNamespace.java @@ -15,10 +15,9 @@ */ package blackberry.web.widget.bf; -import blackberry.web.widget.bf.navigationcontroller.NavigationController; import net.rim.device.api.script.Scriptable; import net.rim.device.api.script.ScriptableFunction; -import java.lang.ref.WeakReference; +import blackberry.web.widget.bf.navigationcontroller.NavigationController; public class NavigationNamespace extends Scriptable { @@ -31,65 +30,31 @@ public class NavigationNamespace extends Scriptable { public static final String LABEL_SET_FOCUS = "setFocus"; public static final String LABEL_GET_FOCUS = "getFocus"; - public static final String LABEL_GET_OLDFOCUS = "getOldFocus"; + public static final String LABEL_GET_PRIORFOCUS = "getPriorFocus"; public static final String LABEL_GET_DIRECTION = "getDirection"; - public static final String LABEL_UPDATE_FOCUS_MAP = "updateFocusMap"; - - private WeakReference _widgetScreenWeakReference; - private String _oldFocused; - private String _currentFocused; - private int _direction; + public static final String LABEL_FOCUS_OUT = "focusOut"; - private SetRimFocus _funcSetRimFocus; - private GetRimFocus _funcGetRimFocus; - private GetOldFocus _funcGetOldFocus; - private GetDirection _funcGetDirection; - private UpdateFocusMap _funcUpdateFocusMap; + public static final String LABEL_ON_SCROLL = "onScroll"; + public static final String LABEL_ON_TRACKPADUP = "onTrackpadUp"; + public static final String LABEL_ON_TRACKPADDOWN = "onTrackpadDown"; - public NavigationNamespace( BrowserFieldScreen widgetScreen ) { - _widgetScreenWeakReference = new WeakReference( widgetScreen ); + private WidgetFieldManager _fieldManager; - _oldFocused = ""; - _currentFocused = ""; - _direction = NavigationController.FOCUS_NAVIGATION_UNDEFINED; - - _funcSetRimFocus = new SetRimFocus(); - _funcGetRimFocus = new GetRimFocus(); - _funcGetOldFocus = new GetOldFocus(); - _funcGetDirection = new GetDirection(); - _funcUpdateFocusMap = new UpdateFocusMap(); - } + private ScriptableFunction _funcSetRimFocus; + private ScriptableFunction _funcGetRimFocus; + private ScriptableFunction _funcGetPriorFocus; + private ScriptableFunction _funcGetDirection; - private BrowserFieldScreen getWidgetScreen() { - Object o = _widgetScreenWeakReference.get(); - if( o instanceof BrowserFieldScreen ) { - return (BrowserFieldScreen) o; - } else { - return null; - } - } + private ScriptableFunction _onScroll; + private ScriptableFunction _focusOut; + private ScriptableFunction _onTrackpadUp; + private ScriptableFunction _onTrackpadDown; - public void setOldFocusedId( String id ) { - if( id == null ) { - _oldFocused = ""; - } else { - _oldFocused = id; - } + public NavigationNamespace( BrowserFieldScreen widgetScreen, WidgetFieldManager fieldManager ) { + _fieldManager = fieldManager; } - - public void setNewFocusedId( String id ) { - if( id == null ) { - _currentFocused = ""; - } else { - _currentFocused = id; - } - } - - public void setDirection( int direction ) { - _direction = direction; - } - + /* @Override */ public Scriptable getParent() { return null; @@ -121,15 +86,24 @@ public Object getField( String name ) throws Exception { return _funcGetRimFocus; } - if( name.equals( LABEL_GET_OLDFOCUS ) ) { - return _funcGetOldFocus; + if( name.equals( LABEL_GET_PRIORFOCUS ) ) { + return _funcGetPriorFocus; } if( name.equals( LABEL_GET_DIRECTION ) ) { return _funcGetDirection; } - if( name.equals( LABEL_UPDATE_FOCUS_MAP ) ) { - return _funcUpdateFocusMap; + + if( name.equals( LABEL_ON_SCROLL ) ) { + return _onScroll; + } + + if( name.equals( LABEL_ON_TRACKPADUP ) ) { + return _onTrackpadUp; + } + + if( name.equals( LABEL_ON_TRACKPADDOWN ) ) { + return _onTrackpadDown; } return UNDEFINED; @@ -137,67 +111,242 @@ public Object getField( String name ) throws Exception { /* @Override */ public boolean putField( String name, Object value ) throws Exception { - return false; - } - - private class SetRimFocus extends ScriptableFunction { - /* @Override */ - public Object invoke( Object thiz, Object[] args ) throws Exception { - if( args != null && args.length == 1 && args[ 0 ] != null ) { - String id = args[ 0 ].toString(); - getWidgetScreen().getNavigationController().setRimFocus( id ); - return UNDEFINED; - } + if( name.equals( LABEL_ON_SCROLL ) ) { + _onScroll = (ScriptableFunction)value; + } - throw new IllegalArgumentException(); + if( name.equals( LABEL_ON_TRACKPADUP ) ) { + _onTrackpadUp = (ScriptableFunction)value; } - } - private class GetRimFocus extends ScriptableFunction { - /* @Override */ - public Object invoke( Object thiz, Object[] args ) throws Exception { - if( args == null || args.length == 0 ) { - return _currentFocused; - } + if( name.equals( LABEL_ON_TRACKPADDOWN ) ) { + _onTrackpadDown = (ScriptableFunction)value; + } - throw new IllegalArgumentException(); + if( name.equals( LABEL_SET_FOCUS ) ) { + _funcSetRimFocus = (ScriptableFunction)value; } - } - private class GetOldFocus extends ScriptableFunction { - /* @Override */ - public Object invoke( Object thiz, Object[] args ) throws Exception { - if( args == null || args.length == 0 ) { - return _oldFocused; - } + if( name.equals( LABEL_GET_FOCUS ) ) { + _funcGetRimFocus = (ScriptableFunction)value; + } - throw new IllegalArgumentException(); + if( name.equals( LABEL_GET_PRIORFOCUS ) ) { + _funcGetPriorFocus = (ScriptableFunction)value; } - } - private class GetDirection extends ScriptableFunction { - /* @Override */ - public Object invoke( Object thiz, Object[] args ) throws Exception { - if( args == null || args.length == 0 ) { - return ( new Integer( _direction ) ); - } + if( name.equals( LABEL_GET_DIRECTION ) ) { + _funcGetDirection = (ScriptableFunction)value; + } - throw new IllegalArgumentException(); + if( name.equals( LABEL_FOCUS_OUT ) ) { + _focusOut = (ScriptableFunction)value; } + + return super.putField(name, value); } /** - * Rescans and repopulates the navigation map + * Object that contains all data needed by JS navigation logic */ - private class UpdateFocusMap extends ScriptableFunction { + private class NavigationData extends Scriptable { + public static final String LABEL_DIRECTION = "direction"; + public static final String LABEL_DELTA = "delta"; + public static final String LABEL_ZOOMSCALE = "zoomScale"; + public static final String LABEL_VIRTUALHEIGHT = "virtualHeight"; + public static final String LABEL_VIRTUALWIDTH = "virtualWidth"; + public static final String LABEL_VERTICALSCROLL = "verticalScroll"; + public static final String LABEL_HORIZONTALSCROLL = "horizontalScroll"; + public static final String LABEL_HEIGHT = "height"; + public static final String LABEL_WIDTH = "width"; + + private int _direction; + private int _delta; + private double _zoomScale; + private int _virtualHeight; + private int _virtualWidth; + private int _verticalScroll; + private int _horizontalScroll; + private int _height; + private int _width; + + /* @Override */ + public Scriptable getParent() { + return null; + } + /* @Override */ - public Object invoke( Object thiz, Object[] args ) throws Exception { - if( args == null || args.length == 0 ) { - getWidgetScreen().getNavigationController().update(); - return UNDEFINED; + public Object getField( String name ) throws Exception { + if( name.equals( LABEL_WIDTH ) ) { + return new Integer( _width ); + } + + if( name.equals( LABEL_HEIGHT ) ) { + return new Integer( _height ); + } + + if( name.equals( LABEL_HORIZONTALSCROLL ) ) { + return new Integer( _horizontalScroll ); + } + + if( name.equals( LABEL_VERTICALSCROLL ) ) { + return new Integer( _verticalScroll ); + } + + if( name.equals( LABEL_VIRTUALWIDTH ) ) { + return new Integer( _virtualWidth ); + } + + if( name.equals( LABEL_VIRTUALHEIGHT ) ) { + return new Integer( _virtualHeight ); + } + + if( name.equals( LABEL_ZOOMSCALE ) ) { + return new Double( _zoomScale ); + } + + if( name.equals( LABEL_DIRECTION ) ) { + return new Integer( _direction ); + } + + if( name.equals( LABEL_DELTA ) ) { + return new Integer( _delta ); + } + + return super.getField(name); + } + + /* @Override */ + public boolean putField( String name, Object value ) throws Exception { + if( name.equals( LABEL_WIDTH ) ) { + _width = ((Integer)value).intValue(); + } + + if( name.equals( LABEL_HEIGHT ) ) { + _height = ((Integer)value).intValue(); + } + + if( name.equals( LABEL_HORIZONTALSCROLL ) ) { + _horizontalScroll = ((Integer)value).intValue(); } + + if( name.equals( LABEL_VERTICALSCROLL ) ) { + _verticalScroll = ((Integer)value).intValue(); + } + + if( name.equals( LABEL_VIRTUALWIDTH ) ) { + _virtualWidth = ((Integer)value).intValue(); + } + + if( name.equals( LABEL_VIRTUALHEIGHT ) ) { + _virtualHeight = ((Integer)value).intValue(); + } + + if( name.equals( LABEL_ZOOMSCALE ) ) { + _zoomScale = ((Double)value).doubleValue(); + } + + if( name.equals( LABEL_DIRECTION ) ) { + _direction = ((Integer)value).intValue(); + } + + if( name.equals( LABEL_DELTA ) ) { + _delta = ((Integer)value).intValue(); + } + + return super.putField(name, value); + } + } + + // call onScroll in navmode.js + public void triggerNavigationDirection( final int direction, final int delta ) { + if( _onScroll == null ) { + return; + } - throw new IllegalArgumentException(); + new Thread() { + public void run() { + try { + NavigationData data = new NavigationData(); + data.putField( NavigationData.LABEL_DIRECTION, new Integer( direction ) ); + data.putField( NavigationData.LABEL_DELTA, new Integer( delta ) ); + data.putField( NavigationData.LABEL_ZOOMSCALE, new Double( _fieldManager.getZoomScale() ) ); + data.putField( NavigationData.LABEL_VIRTUALHEIGHT, new Integer( _fieldManager.getVirtualHeight() ) ); + data.putField( NavigationData.LABEL_VIRTUALWIDTH, new Integer( _fieldManager.getVirtualWidth() ) ); + data.putField( NavigationData.LABEL_VERTICALSCROLL, new Integer( _fieldManager.getVerticalScroll() ) ); + data.putField( NavigationData.LABEL_HORIZONTALSCROLL, new Integer( _fieldManager.getHorizontalScroll() ) ); + data.putField( NavigationData.LABEL_HEIGHT, new Integer( _fieldManager.getHeight() ) ); + data.putField( NavigationData.LABEL_WIDTH, new Integer( _fieldManager.getWidth() ) ); + + Object[] result = new Object[ 1 ]; + result[ 0 ] = data; + + // Pass the event back to the JavaScript callback + ScriptableFunction onScroll = _onScroll; + onScroll.invoke( onScroll, result ); + } catch( Exception e ) { + throw new RuntimeException( e.getMessage() ); + } + } + }.start(); + } + + // call onMouseDown in navmode.js + public void triggerNavigationMouseDown() { + if( _onTrackpadDown == null ) { + return; } + + new Thread() { + public void run() { + try { + Object[] result = new Object[ 0 ]; + + // Pass the event back to the JavaScript callback + ScriptableFunction onMouseDown = _onTrackpadDown; + onMouseDown.invoke( onMouseDown, result ); + } catch( Exception e ) { + throw new RuntimeException( e.getMessage() ); + } + } + }.start(); + } + + // call onMouseUp in navmode.js + public void triggerNavigationMouseUp() { + if( _onTrackpadUp == null ) { + return; + } + + new Thread() { + public void run() { + try { + Object[] result = new Object[ 0 ]; + + // Pass the event back to the JavaScript callback + ScriptableFunction onMouseUp = _onTrackpadUp; + onMouseUp.invoke( onMouseUp, result ); + } catch( Exception e ) { + throw new RuntimeException( e.getMessage() ); + } + } + }.start(); + } + + public void triggerNavigationFocusOut() { + + new Thread() { + public void run() { + try { + Object[] result = new Object[ 0 ]; + + // Pass the event back to the JavaScript callback + ScriptableFunction focusOut = _focusOut; + focusOut.invoke( focusOut, result ); + } catch( Exception e ) { + throw new RuntimeException( e.getMessage() ); + } + } + }.start(); } } diff --git a/framework/src/blackberry/web/widget/bf/WidgetBrowserFieldListener.java b/framework/src/blackberry/web/widget/bf/WidgetBrowserFieldListener.java index 22184db..5f425dc 100644 --- a/framework/src/blackberry/web/widget/bf/WidgetBrowserFieldListener.java +++ b/framework/src/blackberry/web/widget/bf/WidgetBrowserFieldListener.java @@ -186,11 +186,13 @@ public void documentCreated( BrowserField browserField, ScriptEngine scriptEngin bfScreen.getPageManager().clearFlags(); } - // For naviagtion mode, add blackberry.focus namespace to JavaScriptExtension. + // For navigation mode, add blackberry.focus namespace to JavaScriptExtension. if( bfScreen.getAppNavigationMode() && document instanceof HTMLDocument ) { // Add our JS navigation extension to JavaScript Engine. if( proxyScriptEngine != null ) { - proxyScriptEngine.addExtension( NavigationNamespace.NAME, bfScreen.getNavigationExtension() ); + proxyScriptEngine.addExtension( NavigationNamespace.NAME, bfScreen.getNavigationExtension() ); + // Load navmode.js into script engine, must be done after blackberry.focus namespace is defined + bfScreen.getNavigationJS().loadFeature( null, null, null, scriptEngine ); } bfScreen.getNavigationController().reset(); } @@ -307,21 +309,21 @@ public void documentLoaded( BrowserField browserField, Document document ) throw */ if( browserField.getDocument() == document ) { // For navigation mode. - if( browserField.getScreen() instanceof BrowserFieldScreen ) { - BrowserFieldScreen bfScreen = (BrowserFieldScreen) browserField.getScreen(); - - if( bfScreen.getAppNavigationMode() && browserField.getDocument() == document ) { - bfScreen.getNavigationController().update(); - - // Add Layout update event listener. - if( document instanceof EventTarget ) { - EventTarget target = (EventTarget) document; - EventListener listener = new UpdateBinsEventListener( browserField ); - target.addEventListener( "DOMNodeInserted", listener, false ); - target.addEventListener( "DOMNodeRemoved", listener, false ); - } - } - } +// if( browserField.getScreen() instanceof BrowserFieldScreen ) { +// BrowserFieldScreen bfScreen = (BrowserFieldScreen) browserField.getScreen(); +// +// if( bfScreen.getAppNavigationMode() && browserField.getDocument() == document ) { +// bfScreen.getNavigationController().update(); +// +// // Add Layout update event listener. +// if( document instanceof EventTarget ) { +// EventTarget target = (EventTarget) document; +// EventListener listener = new UpdateBinsEventListener( browserField ); +// target.addEventListener( "DOMNodeInserted", listener, false ); +// target.addEventListener( "DOMNodeRemoved", listener, false ); +// } +// } +// } // Pop the loading screeen if it is displayed. if( browserField.getScreen() instanceof BrowserFieldScreen ) { @@ -405,32 +407,33 @@ private String readJSContent( String jsURI ) { return jsContent; } - private static class UpdateBinsEventListener implements EventListener { - private WeakReference _browserFieldWeakReference; - - UpdateBinsEventListener( BrowserField browserField ) { - super(); - _browserFieldWeakReference = new WeakReference( browserField ); - } - - private BrowserField getBrowserField() { - Object o = _browserFieldWeakReference.get(); - if( o instanceof BrowserField ) { - return (BrowserField) o; - } else { - return null; - } - } - - public void handleEvent( Event evt ) { - Screen screen = getBrowserField().getScreen(); - if( screen instanceof BrowserFieldScreen ) { - BrowserFieldScreen bfScreen = (BrowserFieldScreen) screen; +// private static class UpdateBinsEventListener implements EventListener { +// private WeakReference _browserFieldWeakReference; +// +// UpdateBinsEventListener( BrowserField browserField ) { +// super(); +// _browserFieldWeakReference = new WeakReference( browserField ); +// } +// +// private BrowserField getBrowserField() { +// Object o = _browserFieldWeakReference.get(); +// if( o instanceof BrowserField ) { +// return (BrowserField) o; +// } else { +// return null; +// } +// } +// +// public void handleEvent( Event evt ) { +// Screen screen = getBrowserField().getScreen(); +// if( screen instanceof BrowserFieldScreen ) { +// BrowserFieldScreen bfScreen = (BrowserFieldScreen) screen; +// +// if( bfScreen.getAppNavigationMode() ) { +// bfScreen.getNavigationController().update(); +// } +// } +// } +// } - if( bfScreen.getAppNavigationMode() ) { - bfScreen.getNavigationController().update(); - } - } - } - } } diff --git a/framework/src/blackberry/web/widget/bf/WidgetFieldManager.java b/framework/src/blackberry/web/widget/bf/WidgetFieldManager.java index ec9eeb1..c6612cf 100644 --- a/framework/src/blackberry/web/widget/bf/WidgetFieldManager.java +++ b/framework/src/blackberry/web/widget/bf/WidgetFieldManager.java @@ -15,20 +15,11 @@ */ package blackberry.web.widget.bf; -import java.util.Hashtable; - -import org.w3c.dom.Node; -import org.w3c.dom.html2.HTMLIFrameElement; - -import blackberry.web.widget.bf.navigationcontroller.NavigationController; - import net.rim.device.api.browser.field2.BrowserField; -import net.rim.device.api.ui.Graphics; import net.rim.device.api.ui.Screen; import net.rim.device.api.ui.TouchEvent; -import net.rim.device.api.ui.XYRect; import net.rim.device.api.ui.container.VerticalFieldManager; -import net.rim.device.api.util.MathUtilities; +import blackberry.web.widget.bf.navigationcontroller.NavigationController; /** * @@ -68,22 +59,25 @@ private BrowserFieldScreen getBrowserFieldScreen() { // Handle the directional event. int direction = -1; + int delta = 0; if( Math.abs( dx ) >= Math.abs( dy ) ) { if( dx > 0 ) { direction = NavigationController.FOCUS_NAVIGATION_RIGHT; } else { direction = NavigationController.FOCUS_NAVIGATION_LEFT; } + delta = dx; } else { if( dy > 0 ) { direction = NavigationController.FOCUS_NAVIGATION_DOWN; } else { direction = NavigationController.FOCUS_NAVIGATION_UP; } + delta = dy; } try { - getBrowserFieldScreen().getNavigationController().handleDirection( direction ); + getBrowserFieldScreen().getNavigationController().handleDirection( direction, delta ); } catch( Exception e ) { } @@ -95,9 +89,10 @@ private BrowserFieldScreen getBrowserFieldScreen() { protected boolean navigationClick( int status, int time ) { if( getBrowserFieldScreen().getAppNavigationMode() ) { - if( getBrowserFieldScreen().getNavigationController().requiresDefaultNavigation() ) { - super.navigationClick( status, time ); - } + // TODO: [RT] figure out what to do with this +// if( getBrowserFieldScreen().getNavigationController().requiresDefaultNavigation() ) { +// super.navigationClick( status, time ); +// } try { getBrowserFieldScreen().getNavigationController().handleClick(); @@ -112,9 +107,10 @@ protected boolean navigationClick( int status, int time ) { protected boolean navigationUnclick( int status, int time ) { if( getBrowserFieldScreen().getAppNavigationMode() ) { - if( getBrowserFieldScreen().getNavigationController().requiresDefaultNavigation() ) { - super.navigationUnclick( status, time ); - } + // TODO: [RT] figure out what to do with this +// if( getBrowserFieldScreen().getNavigationController().requiresDefaultNavigation() ) { +// super.navigationUnclick( status, time ); +// } try { getBrowserFieldScreen().getNavigationController().handleUnclick(); @@ -127,140 +123,141 @@ protected boolean navigationUnclick( int status, int time ) { return super.navigationUnclick( status, time ); } - /* override */public void paint( Graphics graphics ) { - super.paint( graphics ); - - // Paint current node if it exists, is not focused, and does not have a hover style. - if( getBrowserFieldScreen().getAppNavigationMode() ) { - if( getBrowserFieldScreen().getNavigationController().requiresDefaultHover() ) { - Node currentNode = getBrowserFieldScreen().getNavigationController().getCurrentFocusNode(); - if( currentNode != null ) { - XYRect position = getPosition( currentNode ); - if( position != null ) { - position = scaleRect( position ); - int oldColor = graphics.getColor(); - graphics.setColor( 0xBBDDFF ); - graphics.drawRoundRect( position.x - 1, position.y - 1, position.width + 2, position.height + 2, 4, 4 ); - graphics.setColor( 0x88AAFF ); - graphics.drawRoundRect( position.x, position.y, position.width, position.height, 4, 4 ); - graphics.setColor( oldColor ); - } - } - } - } - } - - public void invalidateNode( Node node ) { - if( node == null ) - return; - XYRect position = getPosition( node ); - if( position == null ) - return; - - position = scaleRect( position ); - invalidate( position.x - 1, position.y - 1, position.width + 2, position.height + 2 ); - } - - public void scrollToNode( Node node ) { - if( node == null ) - return; - XYRect position = getPosition( node ); - if( position == null ) - return; - - position = scaleRect( position ); - scrollToRect( position ); - } - - public void scrollDown() { - int newVerticalScroll = Math.min( getVerticalScroll() + scaleValue( SAFE_MARGIN ), getVirtualHeight() - getHeight() ); - setVerticalScroll( newVerticalScroll ); - } - - public void scrollUp() { - int newVerticalScroll = Math.max( getVerticalScroll() - scaleValue( SAFE_MARGIN ), 0 ); - setVerticalScroll( newVerticalScroll ); - } - - public void scrollRight() { - int newHorizontalScroll = Math.min( getHorizontalScroll() + scaleValue( SAFE_MARGIN ), getVirtualWidth() - getWidth() ); - setHorizontalScroll( newHorizontalScroll ); - } - - public void scrollLeft() { - int newHorizontalScroll = Math.max( getHorizontalScroll() - scaleValue( SAFE_MARGIN ), 0 ); - setHorizontalScroll( newHorizontalScroll ); - } - - public static final int SAFE_MARGIN = 30; - - private void scrollToRect( XYRect rect ) { - // Check vertical scroll. - int verticalScroll = getVerticalScroll(); - int newVerticalScroll = verticalScroll; - - if( rect.y < verticalScroll ) { - newVerticalScroll = Math.max( rect.y - scaleValue( SAFE_MARGIN ), 0 ); - } else if( rect.y + rect.height > verticalScroll + getHeight() ) { - newVerticalScroll = Math.min( rect.y + rect.height - getHeight() + scaleValue( SAFE_MARGIN ), getVirtualHeight() - - getHeight() ); - } - - if( newVerticalScroll - verticalScroll != 0 ) { - setVerticalScroll( newVerticalScroll ); - } - - // Check horizontal scroll. - int horizontalScroll = getHorizontalScroll(); - int newHorizontalScroll = horizontalScroll; - - if( rect.width >= getWidth() ) { - newHorizontalScroll = Math.max( rect.x, 0 ); - } else if( rect.x < horizontalScroll ) { - newHorizontalScroll = Math.max( rect.x - scaleValue( SAFE_MARGIN ), 0 ); - } else if( rect.x + rect.width > horizontalScroll + getWidth() ) { - newHorizontalScroll = Math.min( rect.x + rect.width - getWidth() + scaleValue( SAFE_MARGIN ), getVirtualWidth() - - getWidth() ); - } - - if( newHorizontalScroll - horizontalScroll != 0 ) { - setHorizontalScroll( newHorizontalScroll ); - } - } - - private int scaleValue( int value ) { - BrowserField bf = getBrowserFieldScreen().getWidgetBrowserField(); - float scale = bf.getZoomScale(); - return MathUtilities.round( value * scale ); - } - - private XYRect scaleRect( XYRect rect ) { - return new XYRect( scaleValue( rect.x ), scaleValue( rect.y ), scaleValue( rect.width ), scaleValue( rect.height ) ); - } - - public int unscaleValue( int value ) { - BrowserField bf = getBrowserFieldScreen().getWidgetBrowserField(); - float scale = bf.getZoomScale(); - return MathUtilities.round( value / scale ); - } - - public XYRect unscaleRect( XYRect rect ) { - return new XYRect( unscaleValue( rect.x ), unscaleValue( rect.y ), unscaleValue( rect.width ), unscaleValue( rect.height ) ); - } - - public XYRect getPosition( Node node ) { - BrowserField bf = getBrowserFieldScreen().getWidgetBrowserField(); - XYRect nodeRect = bf.getNodePosition( node ); - - // Check for iframe parent and adjust the coordinates if found - HTMLIFrameElement iframeRect = getIFrameForNode( node ); - if( iframeRect != null && nodeRect != null ){ - nodeRect.x = nodeRect.x + bf.getNodePosition( iframeRect ).x; - nodeRect.y = nodeRect.y + bf.getNodePosition( iframeRect ).y; - } - - return nodeRect; - } + // TODO: [RT] Confirm with Tim that it is ok to lose default hover +// /* override */public void paint( Graphics graphics ) { +// super.paint( graphics ); +// +// // Paint current node if it exists, is not focused, and does not have a hover style. +// if( getBrowserFieldScreen().getAppNavigationMode() ) { +// if( getBrowserFieldScreen().getNavigationController().requiresDefaultHover() ) { +// Node currentNode = getBrowserFieldScreen().getNavigationController().getCurrentFocusNode(); +// if( currentNode != null ) { +// XYRect position = getPosition( currentNode ); +// if( position != null ) { +// position = scaleRect( position ); +// int oldColor = graphics.getColor(); +// graphics.setColor( 0xBBDDFF ); +// graphics.drawRoundRect( position.x - 1, position.y - 1, position.width + 2, position.height + 2, 4, 4 ); +// graphics.setColor( 0x88AAFF ); +// graphics.drawRoundRect( position.x, position.y, position.width, position.height, 4, 4 ); +// graphics.setColor( oldColor ); +// } +// } +// } +// } +// } + +// public void invalidateNode( Node node ) { +// if( node == null ) +// return; +// XYRect position = getPosition( node ); +// if( position == null ) +// return; +// +// position = scaleRect( position ); +// invalidate( position.x - 1, position.y - 1, position.width + 2, position.height + 2 ); +// } +// +// public void scrollToNode( Node node ) { +// if( node == null ) +// return; +// XYRect position = getPosition( node ); +// if( position == null ) +// return; +// +// position = scaleRect( position ); +// scrollToRect( position ); +// } +// +// public void scrollDown() { +// int newVerticalScroll = Math.min( getVerticalScroll() + scaleValue( SAFE_MARGIN ), getVirtualHeight() - getHeight() ); +// setVerticalScroll( newVerticalScroll ); +// } +// +// public void scrollUp() { +// int newVerticalScroll = Math.max( getVerticalScroll() - scaleValue( SAFE_MARGIN ), 0 ); +// setVerticalScroll( newVerticalScroll ); +// } +// +// public void scrollRight() { +// int newHorizontalScroll = Math.min( getHorizontalScroll() + scaleValue( SAFE_MARGIN ), getVirtualWidth() - getWidth() ); +// setHorizontalScroll( newHorizontalScroll ); +// } +// +// public void scrollLeft() { +// int newHorizontalScroll = Math.max( getHorizontalScroll() - scaleValue( SAFE_MARGIN ), 0 ); +// setHorizontalScroll( newHorizontalScroll ); +// } +// +// public static final int SAFE_MARGIN = 30; +// +// private void scrollToRect( XYRect rect ) { +// // Check vertical scroll. +// int verticalScroll = getVerticalScroll(); +// int newVerticalScroll = verticalScroll; +// +// if( rect.y < verticalScroll ) { +// newVerticalScroll = Math.max( rect.y - scaleValue( SAFE_MARGIN ), 0 ); +// } else if( rect.y + rect.height > verticalScroll + getHeight() ) { +// newVerticalScroll = Math.min( rect.y + rect.height - getHeight() + scaleValue( SAFE_MARGIN ), getVirtualHeight() +// - getHeight() ); +// } +// +// if( newVerticalScroll - verticalScroll != 0 ) { +// setVerticalScroll( newVerticalScroll ); +// } +// +// // Check horizontal scroll. +// int horizontalScroll = getHorizontalScroll(); +// int newHorizontalScroll = horizontalScroll; +// +// if( rect.width >= getWidth() ) { +// newHorizontalScroll = Math.max( rect.x, 0 ); +// } else if( rect.x < horizontalScroll ) { +// newHorizontalScroll = Math.max( rect.x - scaleValue( SAFE_MARGIN ), 0 ); +// } else if( rect.x + rect.width > horizontalScroll + getWidth() ) { +// newHorizontalScroll = Math.min( rect.x + rect.width - getWidth() + scaleValue( SAFE_MARGIN ), getVirtualWidth() +// - getWidth() ); +// } +// +// if( newHorizontalScroll - horizontalScroll != 0 ) { +// setHorizontalScroll( newHorizontalScroll ); +// } +// } +// +// private int scaleValue( int value ) { +// BrowserField bf = getBrowserFieldScreen().getWidgetBrowserField(); +// float scale = bf.getZoomScale(); +// return MathUtilities.round( value * scale ); +// } +// +// private XYRect scaleRect( XYRect rect ) { +// return new XYRect( scaleValue( rect.x ), scaleValue( rect.y ), scaleValue( rect.width ), scaleValue( rect.height ) ); +// } +// +// public int unscaleValue( int value ) { +// BrowserField bf = getBrowserFieldScreen().getWidgetBrowserField(); +// float scale = bf.getZoomScale(); +// return MathUtilities.round( value / scale ); +// } +// +// public XYRect unscaleRect( XYRect rect ) { +// return new XYRect( unscaleValue( rect.x ), unscaleValue( rect.y ), unscaleValue( rect.width ), unscaleValue( rect.height ) ); +// } +// +// public XYRect getPosition( Node node ) { +// BrowserField bf = getBrowserFieldScreen().getWidgetBrowserField(); +// XYRect nodeRect = bf.getNodePosition( node ); +// +// // Check for iframe parent and adjust the coordinates if found +// HTMLIFrameElement iframeRect = getIFrameForNode( node ); +// if( iframeRect != null && nodeRect != null ){ +// nodeRect.x = nodeRect.x + bf.getNodePosition( iframeRect ).x; +// nodeRect.y = nodeRect.y + bf.getNodePosition( iframeRect ).y; +// } +// +// return nodeRect; +// } /** * Overrides the touch event handler. @@ -286,19 +283,24 @@ protected boolean touchEvent( TouchEvent message ){ return false; } - /** - * Get the iframe parent of the specified node. - * Returns null if the node does not have an iframe parent. - * @param node - * @return HTMLIFrameElement parent of the specified node - */ - private HTMLIFrameElement getIFrameForNode( Node node ){ - Hashtable iframeHashtable = getBrowserFieldScreen().getNavigationController().getIFrameHashtable(); - HTMLIFrameElement iframe = null; - Object potentialIframe = iframeHashtable.get( node ); - if( potentialIframe instanceof HTMLIFrameElement ){ - iframe = ( HTMLIFrameElement ) potentialIframe; - } - return iframe; - } +// /** +// * Get the iframe parent of the specified node. +// * Returns null if the node does not have an iframe parent. +// * @param node +// * @return HTMLIFrameElement parent of the specified node +// */ +// private HTMLIFrameElement getIFrameForNode( Node node ){ +// Hashtable iframeHashtable = getBrowserFieldScreen().getNavigationController().getIFrameHashtable(); +// HTMLIFrameElement iframe = null; +// Object potentialIframe = iframeHashtable.get( node ); +// if( potentialIframe instanceof HTMLIFrameElement ){ +// iframe = ( HTMLIFrameElement ) potentialIframe; +// } +// return iframe; +// } + + public float getZoomScale() { + BrowserField bf = getBrowserFieldScreen().getWidgetBrowserField(); + return bf.getZoomScale(); + } } diff --git a/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationController.java b/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationController.java index e82cd1d..d50a006 100644 --- a/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationController.java +++ b/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationController.java @@ -1,46 +1,33 @@ /* -* Copyright 2010-2011 Research In Motion Limited. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package blackberry.web.widget.bf.navigationcontroller; import java.util.Hashtable; -import java.util.Vector; import net.rim.device.api.browser.field2.BrowserField; import net.rim.device.api.system.Application; -import net.rim.device.api.ui.XYRect; import org.w3c.dom.Attr; -import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; -import org.w3c.dom.events.DocumentEvent; -import org.w3c.dom.events.Event; -import org.w3c.dom.events.EventTarget; -import org.w3c.dom.html2.HTMLButtonElement; -import org.w3c.dom.html2.HTMLInputElement; -import org.w3c.dom.html2.HTMLObjectElement; -import org.w3c.dom.html2.HTMLSelectElement; -import org.w3c.dom.html2.HTMLTextAreaElement; import blackberry.core.threading.Dispatcher; -import blackberry.core.threading.GenericDispatcherEvent; import blackberry.web.widget.bf.BrowserFieldScreen; import blackberry.web.widget.bf.NavigationNamespace; import blackberry.web.widget.bf.WidgetFieldManager; -import blackberry.web.widget.device.DeviceInfo; /** * NavigationController @@ -48,208 +35,86 @@ final public class NavigationController { // Constants - public static final int FOCUS_NAVIGATION_UNDEFINED = -1; - public static final int FOCUS_NAVIGATION_RIGHT = 0; - public static final int FOCUS_NAVIGATION_LEFT = 1; - public static final int FOCUS_NAVIGATION_UP = 2; - public static final int FOCUS_NAVIGATION_DOWN = 3; - - public static final String RIM_FOCUSABLE = "x-blackberry-focusable"; - public static final String RIM_FOCUSED = "x-blackberry-focused"; - public static final String INITIAL_FOCUS = "x-blackberry-initialFocus"; - public static final String DEFAULT_HOVER_EFFECT = "x-blackberry-defaultHoverEffect"; - - public static final int NAVIGATION_EVENT_DIRECTION = 0; - public static final int NAVIGATION_EVENT_CLICK = 1; - public static final int NAVIGATION_EVENT_UNCLICK = 2; - public static final int NAVIGATION_EVENT_INITFOCUS = 3; + public static final int FOCUS_NAVIGATION_UNDEFINED = -1; + public static final int FOCUS_NAVIGATION_RIGHT = 0; + public static final int FOCUS_NAVIGATION_LEFT = 1; + public static final int FOCUS_NAVIGATION_UP = 2; + public static final int FOCUS_NAVIGATION_DOWN = 3; + + public static final String RIM_FOCUSABLE = "x-blackberry-focusable"; + public static final String RIM_FOCUSED = "x-blackberry-focused"; + public static final String INITIAL_FOCUS = "x-blackberry-initialFocus"; + public static final String DEFAULT_HOVER_EFFECT = "x-blackberry-defaultHoverEffect"; + + public static final int NAVIGATION_EVENT_DIRECTION = 0; + public static final int NAVIGATION_EVENT_CLICK = 1; + public static final int NAVIGATION_EVENT_UNCLICK = 2; + public static final int NAVIGATION_EVENT_INITFOCUS = 3; // Cached references to BrowserFieldScreen components /*package*/ - BrowserField _browserField; - NavigationNamespace _navigationNamespace; - WidgetFieldManager _widgetFieldManager; - - // Members /*package*/ - Node _currentFocusNode; - boolean _currentNodeHovered; - boolean _currentNodeFocused; - Document _dom; - Vector _focusableNodes; - private boolean _pageLoaded; - boolean _defaultHoverEffect; - Hashtable _iframeHashtable; + BrowserField _browserField; + NavigationNamespace _navigationNamespace; + WidgetFieldManager _widgetFieldManager; + Hashtable _iframeHashtable; /* Creates a new NavigationController. */ public NavigationController( BrowserFieldScreen widgetScreen ) { _browserField = widgetScreen.getWidgetBrowserField(); _navigationNamespace = widgetScreen.getNavigationExtension(); _widgetFieldManager = widgetScreen.getWidgetFieldManager(); - _currentNodeHovered = true; - _defaultHoverEffect = true; _iframeHashtable = new Hashtable(); } public void reset() { clearEventQueue(); - _dom = null; - _currentFocusNode = null; - _currentNodeHovered = true; - _currentNodeFocused = false; - _focusableNodes = null; - _pageLoaded = false; - _defaultHoverEffect = true; } - + public void clearEventQueue() { synchronized( Application.getEventLock() ) { Dispatcher.getInstance().clear( this ); } } - public void update() { - if( !_pageLoaded ) { - _pageLoaded = true; - Dispatcher.getInstance().dispatch( - new NavigationMapUpdateDispatcherEvent( this, this, true ) ); - } else { - if( _currentFocusNode != null ) { - if( !isValidFocusableNode( _currentFocusNode ) ) { - _currentFocusNode = null; - } else { - _currentNodeHovered = _browserField.setHover( _currentFocusNode, true ); - // Scroll to the current focus node - _widgetFieldManager.scrollToNode( _currentFocusNode ); - } - } - Dispatcher.getInstance().dispatch( - new NavigationMapUpdateDispatcherEvent( this, this, false ) ); - } - } - - public void setRimFocus( String id ) { - if( id.length() == 0 ) { - focusOut(); - return; - } - Node nextFocusNode = null; - nextFocusNode = _dom.getElementById( id ); - if( nextFocusNode != null ) { - if( !isValidFocusableNode( nextFocusNode ) ) { - nextFocusNode = null; - } - } - if( nextFocusNode != null ) { - setFocus( nextFocusNode ); - } - } - - public Node getCurrentFocusNode() { - return _currentFocusNode; - } - - public boolean requiresDefaultHover() { - return ( _currentFocusNode != null && !_currentNodeHovered && _defaultHoverEffect ); - } - - public boolean requiresDefaultNavigation() { - return ( _currentFocusNode != null && _currentNodeFocused && requiresNavigation( _currentFocusNode ) ); - } - /* Handles the navigation movement based on direction */ - public void handleDirection( int direction ) { - dispatchUiEvent( NAVIGATION_EVENT_DIRECTION, direction ); + public void handleDirection( int direction, int delta ) { + dispatchUiEvent( NAVIGATION_EVENT_DIRECTION, direction, delta ); } - + public void handleClick() { - dispatchUiEvent( NAVIGATION_EVENT_CLICK, FOCUS_NAVIGATION_UNDEFINED ); + dispatchUiEvent( NAVIGATION_EVENT_CLICK, FOCUS_NAVIGATION_UNDEFINED, 0 ); // TODO: [RT] find out how to get delta } - + public void handleUnclick() { - dispatchUiEvent( NAVIGATION_EVENT_UNCLICK, FOCUS_NAVIGATION_UNDEFINED ); + dispatchUiEvent( NAVIGATION_EVENT_UNCLICK, FOCUS_NAVIGATION_UNDEFINED, 0 ); // TODO: [RT] find out how to get delta } - + public void handleInitFocus() { - dispatchUiEvent(NAVIGATION_EVENT_INITFOCUS, FOCUS_NAVIGATION_UNDEFINED); + dispatchUiEvent( NAVIGATION_EVENT_INITFOCUS, FOCUS_NAVIGATION_UNDEFINED, 0 ); // TODO: [RT] find out how to get delta } - public void setIFrameHashtable( Hashtable newHash ){ - _iframeHashtable = newHash; + public void setIFrameHashtable( Hashtable newHash ) { + _iframeHashtable = newHash; } - - public Hashtable getIFrameHashtable(){ - return _iframeHashtable; + + public Hashtable getIFrameHashtable() { + return _iframeHashtable; } - + /** * Deselects the node with the current navigation focus */ - public void deselectFocusedNode(){ - focusOut(); - } - - // Internal methods... - - private boolean dispatchUiEvent( int eventType, int direction ) { - if( _dom == null ) - return false; - return Dispatcher.getInstance().dispatch( - new NavigationUiDispatcherEvent( this, this, eventType, direction ) ); - } - - void setFocus( Node node ) { - if( node == null ) - return; - - focusOut(); - - // Focus in... - _currentFocusNode = node; - - String id = getNamedAttibute( node, "id" ); - _navigationNamespace.setNewFocusedId( id ); - - // Create a synthetic mouse over Event - fireMouseEvent( "mouseover", node ); - - // Call BF setHover - _currentNodeHovered = _browserField.setHover( node, true ); - - if( isAutoFocus( node ) ) { - _currentNodeFocused = _browserField.setFocus( node, true ); - } - - // Scroll to the current focus node - _widgetFieldManager.scrollToNode( node ); - _widgetFieldManager.invalidateNode( node ); + public void deselectFocusedNode() { + _navigationNamespace.triggerNavigationFocusOut(); } - void focusOut() { - if( _currentFocusNode != null ) { - String id = getNamedAttibute( _currentFocusNode, "id" ); - _navigationNamespace.setOldFocusedId( id ); - - // Disable BF focus - if( _currentNodeFocused ) { - _browserField.setFocus( _currentFocusNode, false ); - _currentNodeFocused = false; - } - - // Disable BF hover - _browserField.setHover( _currentFocusNode, false ); - - // Create a synthetic mouseout Event - fireMouseEvent( "mouseout", _currentFocusNode ); - - // Invalidate the area of old _currentFocusNode - _widgetFieldManager.invalidateNode( _currentFocusNode ); + // Internal methods... - _currentFocusNode = null; - _navigationNamespace.setNewFocusedId( null ); - } + private boolean dispatchUiEvent( int eventType, int direction, int delta ) { + return Dispatcher.getInstance().dispatch( new NavigationUiDispatcherEvent( this, this, eventType, direction, delta ) ); } // Utility functions... - + String getNamedAttibute( Node node, String name ) { if( node == null ) return null; @@ -270,84 +135,15 @@ boolean isFocusableDisabled( Node node ) { return false; } - private static final String SUPPRESS_NAVIGATION_INPUT_TYPES = "|checkbox|radio|button|"; - private static final String AUTO_FOCUS_INPUT_TYPES = "|color|date|month|time|week|email|number|password|search|text|url|"; - private static final String REQUIRE_CLICK_INPUT_TYPES = "|file|"; - - private boolean isAutoFocus( Node node ) { - if( node instanceof HTMLInputElement ) { - String type = ( (HTMLInputElement) node ).getType(); - return AUTO_FOCUS_INPUT_TYPES.indexOf( type ) > 0; - } - if( node instanceof HTMLSelectElement ) { - if ( DeviceInfo.isBlackBerry6() ) - // WebKit will autofocus the select element - return false; - else{ - HTMLSelectElement select = ( HTMLSelectElement ) node; - return !select.getMultiple(); - } - } - return ( node instanceof HTMLTextAreaElement ); + void triggerNavigationDirection( int direction, int delta ) { + _navigationNamespace.triggerNavigationDirection( direction, delta ); } - private boolean requiresNavigation( Node node ) { - if( node instanceof HTMLInputElement ) { - String type = ( (HTMLInputElement) node ).getType(); - return ( SUPPRESS_NAVIGATION_INPUT_TYPES.indexOf( type ) < 0 ); - } - if( node instanceof HTMLSelectElement ) - return true; - if( node instanceof HTMLTextAreaElement ) - return true; - if( node instanceof HTMLButtonElement ) - return true; - return ( node instanceof HTMLObjectElement ); + void triggerNavigationMouseDown() { + _navigationNamespace.triggerNavigationMouseDown(); } - boolean fireMouseEvent( final String type, final Node node ) { - if( node == null ) - return false; - - // if the JS triggered by this mouse event blocks this thread for too long, the browser will timeout/crash. - // Dispatch it into another thread. - new GenericDispatcherEvent() { - protected void dispatch() { - try { - DocumentEvent domEvent = (DocumentEvent) _dom; - Event mouseEvent = domEvent.createEvent( "MouseEvents" ); - mouseEvent.initEvent( type, true, true ); - ( (EventTarget) node ).dispatchEvent( mouseEvent ); - } catch( Exception e ) { - } - } - }.Dispatch(); - - return true; - } - - boolean isValidFocusableNode( Node node ) { - if( node == null ) - return false; - XYRect nodeRect = _widgetFieldManager.getPosition( node ); - return !( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 ); - } - - /** - * Determines if the current control is a special case that requires a click event in WebKit. - * @param node - * @return - */ - boolean currentNodeRequiresClickInWebKit(){ - if( _currentFocusNode == null ){ - return false; - } - if( DeviceInfo.isBlackBerry6() ){ - if( _currentFocusNode instanceof HTMLInputElement ){ - String type = ( ( HTMLInputElement ) _currentFocusNode ).getType(); - return REQUIRE_CLICK_INPUT_TYPES.indexOf( type ) > 0; - } - } - return false; + void triggerNavigationMouseUp() { + _navigationNamespace.triggerNavigationMouseUp(); } } diff --git a/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationExtension.java b/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationExtension.java new file mode 100644 index 0000000..4f2646c --- /dev/null +++ b/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationExtension.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package blackberry.web.widget.bf.navigationcontroller; + +import java.io.IOException; +import java.io.InputStream; + +import org.w3c.dom.Document; + +import net.rim.device.api.browser.field2.BrowserField; +import net.rim.device.api.io.IOUtilities; +import net.rim.device.api.script.ScriptEngine; +import net.rim.device.api.web.WidgetConfig; +import net.rim.device.api.web.WidgetExtension; + +/** + * Extension for injecting navmode.js into the script engine + */ +public class NavigationExtension implements WidgetExtension { + + private String navmodeURL = "/js/navmode.js"; + private String navmodeContent; + + public NavigationExtension() { + loadJS(); + } + + public String[] getFeatureList() { + return null; + } + + public void loadFeature( String feature, String version, Document doc, ScriptEngine scriptEngine ) throws Exception { + // Load navmode content into script engine and execute + Object compiledScript = scriptEngine.compileScript( navmodeContent ); + scriptEngine.executeCompiledScript( compiledScript, null ); + } + + + public void register( WidgetConfig arg0, BrowserField arg1 ) { + return; + } + + public void unloadFeatures( Document arg0 ) { + return; + } + + /* + * Method that loads contents of navmode JS file to be executed by the + * Script Engine + */ + private void loadJS() { + InputStream input = null; + try { + input = this.getClass().getResourceAsStream( navmodeURL ); + byte[] data = IOUtilities.streamToBytes( input ); + navmodeContent = new String( data ); + } catch( IOException e ) { + // Should not happen + // Can only be thrown if I/O error converting input stream + // into byte array + } finally { + try { + if( input != null ) { + input.close(); + } + } catch( IOException e ) { + // Should not happen + } + } + } +} diff --git a/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationMapUpdateDispatcherEvent.java b/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationMapUpdateDispatcherEvent.java deleted file mode 100644 index ae54ebd..0000000 --- a/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationMapUpdateDispatcherEvent.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2010-2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package blackberry.web.widget.bf.navigationcontroller; - -import java.util.Hashtable; -import java.util.Vector; - -import net.rim.device.api.ui.XYRect; - -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.ElementTraversal; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.NodeSelector; -import org.w3c.dom.html2.HTMLHeadElement; -import org.w3c.dom.html2.HTMLIFrameElement; -import org.w3c.dom.html2.HTMLInputElement; -import org.w3c.dom.html2.HTMLMetaElement; -import org.w3c.dom.html2.HTMLSelectElement; - -import blackberry.core.threading.DispatchableEvent; - -/** - * NavigationMapUpdateDispatcherEvent - */ -class NavigationMapUpdateDispatcherEvent extends DispatchableEvent { - - private final NavigationController _navigationController; - private boolean _pageLoaded; - - NavigationMapUpdateDispatcherEvent( final NavigationController navigationController, - final NavigationController context, boolean pageLoaded ) { - super( context ); - _navigationController = navigationController; - _pageLoaded = pageLoaded; - - } - - // << DispatchableEvent >> - protected void dispatch() { - _navigationController._dom = _navigationController._browserField.getDocument(); - - // Reset iframe hashtable - Hashtable iframeHashtable = _navigationController.getIFrameHashtable(); - iframeHashtable.clear(); - _navigationController.setIFrameHashtable( iframeHashtable ); - - if( _pageLoaded ) { - // Create navigation map - _navigationController._focusableNodes = populateFocusableNodes( true, _navigationController._dom ); - _navigationController._defaultHoverEffect = isDefaultHoverEffectEnabled( _navigationController._dom ); - // Set first focus - Node firstFocusNode = findInitialFocusNode(); - if( firstFocusNode == null ) { - _navigationController.handleInitFocus(); - } else { - _navigationController.setFocus( firstFocusNode ); - } - } else { - // Update navigation map - _navigationController._focusableNodes = populateFocusableNodes( false, _navigationController._dom ); - if( _navigationController._currentFocusNode != null ) { - if( !_navigationController.isValidFocusableNode( _navigationController._currentFocusNode ) ) { - _navigationController._currentFocusNode = null; - } - } - } - return; - } - - private Node findInitialFocusNode() { - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - for( int i = 0; i < _navigationController._focusableNodes.size(); i++ ) { - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 ) { - continue; - } - if( _navigationController.isFocusableDisabled( node ) ) { - continue; - } - if( isInitialFocusNode( node ) ) { - return node; - } - } - return null; - } - - private Vector populateFocusableNodes( boolean firstLoad, final Document targetDom ) { - Vector focusableNodes = new Vector(); - NodeSelector selector = (NodeSelector) targetDom; - NodeList nodeList = selector - .querySelectorAll( "textarea:not([x-blackberry-focusable=false]),a:not([x-blackberry-focusable=false]),input:not([x-blackberry-focusable=false]),select:not([x-blackberry-focusable=false]),button:not([x-blackberry-focusable=false]),[x-blackberry-focusable=true]" ); - for( int i = 0; i < nodeList.getLength(); i++ ) { - Node node = nodeList.item( i ); - if( node instanceof HTMLSelectElement && ( (HTMLSelectElement) node ).getMultiple() ) { - } else if( node instanceof HTMLInputElement && ( (HTMLInputElement) node ).getType().equals( "hidden" ) ) { - } else { - - // Check for iframes - IFrameSearchResult result = checkForIframe(node); - - // Append focusable nodes of the iframe if an iframe was found in the search - if( result.hasIFrameNode() ){ - Vector iframeFocusableNodes = result.getIFrameFocusableNodes(); - Node iframeChildNode; - int size = iframeFocusableNodes.size(); - for( int j = 0; j < size ; j++ ){ - iframeChildNode = (Node)iframeFocusableNodes.elementAt( j ); - focusableNodes.addElement( iframeChildNode ); - - /* Add the iframe to the child-parent hash. - * Used later to calculate proper XY coordinates */ - Hashtable iframeHashtable = _navigationController.getIFrameHashtable(); - iframeHashtable.put( iframeChildNode, result.getTargetNode() ); - _navigationController.setIFrameHashtable( iframeHashtable ); - } - } - /* If an iframe was not found, then the target node is just a - regular focusable node. Add it to the list*/ - else{ - focusableNodes.addElement( result.getTargetNode() ); - } - } - } - return focusableNodes; - } - - - /** - * - * The function checks if the dom element is an iframe or not. - * If it is an iframe it runs the selector query to get the node list of - * focusable elements recursively. * - * @param node - * @return IFrameSearchResult containing results of the search - */ - private IFrameSearchResult checkForIframe( Node node ){ - - IFrameSearchResult searchResult; - if( node instanceof HTMLIFrameElement ) - { - HTMLIFrameElement iframeNode = (HTMLIFrameElement) node; - Document iframeDom = iframeNode.getContentDocument(); //for now a single banner - Vector iframeFocusableNodes = populateFocusableNodes( true, iframeDom ); - - // Create result container - searchResult = new IFrameSearchResult( node ); - searchResult.setIFrameFocusableNodes( iframeFocusableNodes ); - } - else { - searchResult = new IFrameSearchResult( node ); - } - return searchResult; - } - - - private boolean isDefaultHoverEffectEnabled( final Document dom ) { - if( dom == null ) - return true; - Element head = null; - Element doc = dom.getDocumentElement(); - if( doc instanceof ElementTraversal ) { - head = ( (ElementTraversal) doc ).getFirstElementChild(); - } - if( !( head instanceof HTMLHeadElement ) ) { - return true; - } - for( Node node = head.getFirstChild(); node != null; node = node.getNextSibling() ) { - if( node instanceof HTMLMetaElement ) { - HTMLMetaElement meta = (HTMLMetaElement) node; - String name = meta.getName(); - String content; - - if( name != null && name.equalsIgnoreCase( NavigationController.DEFAULT_HOVER_EFFECT ) ) { - content = meta.getContent(); - if( content != null && content.equalsIgnoreCase( "false" ) ) { - return false; - } - } - } - } - return true; - } - - private boolean isInitialFocusNode( final Node node ) { - NamedNodeMap nnm = node.getAttributes(); - if( nnm != null ) { - Node att = nnm.getNamedItem( NavigationController.INITIAL_FOCUS ); - if( ( att instanceof Attr ) && ( (Attr) att ).getValue().equals( "true" ) ) { - return true; - } - } - return false; - } - - /** - * Container used to store results of iframe checks. If the target node is - * an iframe, the focusable nodes within the iframe should be stored. - */ - private static class IFrameSearchResult { - private Node _targetNode; - private Vector _iframeFocusableNodes; - - IFrameSearchResult(final Node targetNode){ - _targetNode = targetNode; - _iframeFocusableNodes = null; - } - - /** - * Sets the list of focusable nodes within the target iframe node. - * @param focusableNodes - */ - public void setIFrameFocusableNodes(Vector focusableNodes){ - _iframeFocusableNodes = focusableNodes; - } - /** - * Checks if the target node is an iframe. - * @return true when target node is an HTMLIFrameElement - */ - public boolean hasIFrameNode(){ - return (_targetNode instanceof HTMLIFrameElement); - } - - /** - * Retrieves target node. - * @return Node used in constructor - */ - public Node getTargetNode(){ - return _targetNode; - } - - /** - * Retrieves focusable nodes found within the target node. - * Will be null if the target node is not an iframe. - * @return - */ - public Vector getIFrameFocusableNodes(){ - return _iframeFocusableNodes; - } - - } -} \ No newline at end of file diff --git a/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationUiDispatcherEvent.java b/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationUiDispatcherEvent.java index d1b87ab..3c57b11 100644 --- a/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationUiDispatcherEvent.java +++ b/framework/src/blackberry/web/widget/bf/navigationcontroller/NavigationUiDispatcherEvent.java @@ -1,703 +1,62 @@ /* -* Copyright 2010-2011 Research In Motion Limited. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package blackberry.web.widget.bf.navigationcontroller; -import net.rim.device.api.ui.XYRect; - -import org.w3c.dom.Node; - import blackberry.core.threading.DispatchableEvent; -import blackberry.web.widget.bf.WidgetFieldManager; /** * NavigationUiDispatcherEvent */ class NavigationUiDispatcherEvent extends DispatchableEvent { - + private final NavigationController _navigationController; - private int _eventType; - private int _direction; + private int _eventType; + private int _direction; + private int _delta; - NavigationUiDispatcherEvent( final NavigationController navigationController, - final NavigationController context, int eventType, int direction ) { + NavigationUiDispatcherEvent( final NavigationController navigationController, final NavigationController context, + int eventType, int direction, int delta ) { super( context ); _navigationController = navigationController; _eventType = eventType; _direction = direction; + _delta = delta; } // << DispatchableEvent >> protected void dispatch() { - switch ( _eventType ) { + switch( _eventType ) { case NavigationController.NAVIGATION_EVENT_DIRECTION: - handleDirection( _direction ); + handleDirection( _direction, _delta ); break; case NavigationController.NAVIGATION_EVENT_CLICK: - if( _navigationController._currentFocusNode == null ) - return; - if( !_navigationController._currentNodeFocused ) { - // Add current focus - if( _navigationController._currentFocusNode != null && !_navigationController._currentNodeFocused ) { - _navigationController._currentNodeFocused = _navigationController._browserField.setFocus( _navigationController._currentFocusNode, true ); - _navigationController._widgetFieldManager.invalidateNode( _navigationController._currentFocusNode ); - } - _navigationController.fireMouseEvent( "mousedown", _navigationController._currentFocusNode ); - } + _navigationController.triggerNavigationMouseDown(); break; case NavigationController.NAVIGATION_EVENT_UNCLICK: - if( _navigationController._currentFocusNode == null ) - return; - if( !_navigationController._currentNodeFocused || _navigationController.currentNodeRequiresClickInWebKit()) { - _navigationController.fireMouseEvent( "mouseup", _navigationController._currentFocusNode ); - _navigationController.fireMouseEvent( "click", _navigationController._currentFocusNode ); - } + _navigationController.triggerNavigationMouseUp(); break; case NavigationController.NAVIGATION_EVENT_INITFOCUS: - Node nd = findHighestFocusableNodeInScreen(); - if (nd != null) { - _navigationController.setFocus(nd); - } break; default: - throw new Error("Invalid event type: " + _eventType); - } - } - - // Call back from NavigationUiDispatcherEvent - private void handleDirection( int direction ) { - - if (direction < NavigationController.FOCUS_NAVIGATION_UNDEFINED || direction > NavigationController.FOCUS_NAVIGATION_DOWN) - throw new Error("Invalid direction: " + direction); - - _navigationController._navigationNamespace.setDirection( direction ); - String attributeValue = null; - - if( _navigationController._currentFocusNode != null ) { - switch( direction ) { - case NavigationController.FOCUS_NAVIGATION_RIGHT: - attributeValue = _navigationController.getNamedAttibute( _navigationController._currentFocusNode, "x-blackberry-onRight" ); - break; - case NavigationController.FOCUS_NAVIGATION_LEFT: - attributeValue = _navigationController.getNamedAttibute( _navigationController._currentFocusNode, "x-blackberry-onLeft" ); - break; - case NavigationController.FOCUS_NAVIGATION_UP: - attributeValue = _navigationController.getNamedAttibute( _navigationController._currentFocusNode, "x-blackberry-onUp" ); - break; - case NavigationController.FOCUS_NAVIGATION_DOWN: - attributeValue = _navigationController.getNamedAttibute( _navigationController._currentFocusNode, "x-blackberry-onDown" ); - break; - default: - throw new Error("Invalid direction: " + direction); - } - } - - if( attributeValue != null && attributeValue.length() > 2 ) { - _navigationController._browserField.executeScript( attributeValue ); - return; - } - - XYRect screenRect = getUnscaledScreenRect(); - - switch ( direction ) { - case NavigationController.FOCUS_NAVIGATION_DOWN: - handleDirectionDown( screenRect ); - break; - case NavigationController.FOCUS_NAVIGATION_UP: - handleDirectionUp( screenRect ); - break; - case NavigationController.FOCUS_NAVIGATION_RIGHT: - handleDirectionRight( screenRect ); - break; - case NavigationController.FOCUS_NAVIGATION_LEFT: - handleDirectionLeft( screenRect ); - break; - } - - if( _navigationController._currentFocusNode != null ) { - _navigationController._currentNodeHovered = _navigationController._browserField.setHover( _navigationController._currentFocusNode, true ); - } - } - - // Support method for handleDirection(int) - private void handleDirectionDown( final XYRect screenRect ) { - Node node = findDownFocusableNode(); - if( node != null ) { - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - if( nodeRect.y <= ( screenRect.y + screenRect.height + WidgetFieldManager.SAFE_MARGIN ) ) { - _navigationController.setFocus( node ); - return; - } - } - // Only scroll down the screen when there is more content underneath - int screenVerticalDelta = _navigationController._widgetFieldManager.unscaleValue( _navigationController._widgetFieldManager - .getVirtualHeight() ) - screenRect.y - screenRect.height; - if( screenVerticalDelta > WidgetFieldManager.SAFE_MARGIN ) { - screenVerticalDelta = WidgetFieldManager.SAFE_MARGIN; - } - if( screenVerticalDelta > 0 ) { - if( _navigationController._currentFocusNode != null ) { - // If current focused node is out of screen, focus out - XYRect currentNodeRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - if( currentNodeRect.y + currentNodeRect.height <= screenRect.y - + screenVerticalDelta ) { - _navigationController.focusOut(); - } - } - _navigationController._widgetFieldManager.scrollDown(); - } - } - - // Support method for handleDirection(int) - private void handleDirectionUp( final XYRect screenRect ) { - Node node = findUpFocusableNode(); - if( node != null ) { - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - if( ( nodeRect.y + nodeRect.height ) > ( screenRect.y - WidgetFieldManager.SAFE_MARGIN ) ) { - _navigationController.setFocus( node ); - return; - } - } - // Only scroll down the screen when there is more content underneath - int screenVerticalDelta = screenRect.y; - if( screenVerticalDelta > WidgetFieldManager.SAFE_MARGIN ) { - screenVerticalDelta = WidgetFieldManager.SAFE_MARGIN; - } - if( screenVerticalDelta > 0 ) { - if( _navigationController._currentFocusNode != null ) { - // If current focused node is out of screen, focus out. - XYRect currentNodeRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - if( currentNodeRect.y > screenRect.y - screenVerticalDelta + screenRect.height ) { - _navigationController.focusOut(); - } - } - _navigationController._widgetFieldManager.scrollUp(); - } - } - - // Support method for handleDirection(int) - private void handleDirectionRight( final XYRect screenRect ) { - Node node = findRightFocusableNode(); - if( node != null ) { - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - if( nodeRect.x <= ( screenRect.x + screenRect.width + WidgetFieldManager.SAFE_MARGIN ) ) { - _navigationController.setFocus( node ); - return; - } - } - // Only scroll down the screen when there is more content underneath. - int screenHorizontalDelta = _navigationController._widgetFieldManager.unscaleValue( _navigationController._widgetFieldManager.getVirtualWidth() ) - - screenRect.x - screenRect.width; - if( screenHorizontalDelta > WidgetFieldManager.SAFE_MARGIN ) { - screenHorizontalDelta = WidgetFieldManager.SAFE_MARGIN; - } - if( screenHorizontalDelta > 0 ) { - if( _navigationController._currentFocusNode != null ) { - // If current focused node is out of screen, focus out. - XYRect currentNodeRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - if( currentNodeRect.x + currentNodeRect.width <= screenRect.x + screenHorizontalDelta ) { - _navigationController.focusOut(); - } - } - _navigationController._widgetFieldManager.scrollRight(); - } - } - - // Support method for handleDirection(int) - private void handleDirectionLeft( final XYRect screenRect ) { - Node node = findLeftFocusableNode(); - if( node != null ) { - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - if( ( nodeRect.x + nodeRect.width ) > ( screenRect.x - WidgetFieldManager.SAFE_MARGIN ) ) { - _navigationController.setFocus( node ); - return; - } - } - // Only scroll down the screen when there is more content underneath. - int screenHorizontalDelta = screenRect.x; - if( screenHorizontalDelta > WidgetFieldManager.SAFE_MARGIN ) { - screenHorizontalDelta = WidgetFieldManager.SAFE_MARGIN; - } - if( screenHorizontalDelta > 0 ) { - if( _navigationController._currentFocusNode != null ) { - // If current focused node is out of screen, focus out. - XYRect currentNodeRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - if( currentNodeRect.x > screenRect.x - screenHorizontalDelta + screenRect.width ) { - _navigationController.focusOut(); - } - } - _navigationController._widgetFieldManager.scrollLeft(); - } - } - - private Node findDownFocusableNode() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - if( _navigationController._currentFocusNode == null || _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ) == -1 ) - return findHighestFocusableNodeInScreen(); - - int index = _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ); - XYRect currentRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - Node downNode = null; - XYRect downRect = null; - XYRect screenRect = getUnscaledScreenRect(); - - for( int i = 0; i < _navigationController._focusableNodes.size(); i++ ) { - if( i == index ) { - continue; - } - - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 - || _navigationController.isFocusableDisabled( node ) ) { - continue; - } - - if( isRectIntersectingVertically( nodeRect, currentRect ) ) { - boolean swap = false; - if( nodeRect.y == currentRect.y ) { - if( nodeRect.height == currentRect.height ) { - if( i > index ) { - return node; - } - } else if( nodeRect.height > currentRect.height ) { - swap = needSwapWithDownRectInPriority( downRect, nodeRect ); - } - } else if( nodeRect.y > currentRect.y ) { - swap = needSwapWithDownRectInPriority( downRect, nodeRect ); - } - if( swap ) { - downNode = node; - downRect = nodeRect; - } - } else if( !isRectIntersectingHorizontally( nodeRect, currentRect ) - && isRectIntersectingVertically( nodeRect, screenRect ) ) { - boolean swap = false; - if( nodeRect.y > currentRect.y ) { - swap = needSwapWithDownRect( downRect, nodeRect ); - } - if( swap ) { - downNode = node; - downRect = nodeRect; - } - } - } - return downNode; - } - - private Node findUpFocusableNode() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - if( _navigationController._currentFocusNode == null || _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ) == -1 ) - return findLowestFocusableNodeInScreen(); - - int index = _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ); - XYRect currentRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - Node upNode = null; - XYRect upRect = null; - XYRect screenRect = getUnscaledScreenRect(); - for( int i = _navigationController._focusableNodes.size() - 1; i >= 0; i-- ) { - if( i == index ) { - continue; - } - - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 - || _navigationController.isFocusableDisabled( node ) ) { - continue; - } - - if( isRectIntersectingVertically( nodeRect, currentRect ) ) { - boolean swap = false; - if( nodeRect.y == currentRect.y ) { - if( nodeRect.height == currentRect.height ) { - if( i < index ) { - return node; - } - } else if( nodeRect.height < currentRect.height ) { - swap = needSwapWithUpRectInPriority( upRect, nodeRect ); - } - } else if( nodeRect.y < currentRect.y ) { - swap = needSwapWithUpRectInPriority( upRect, nodeRect ); - } - if( swap ) { - upNode = node; - upRect = nodeRect; - } - } else if( !isRectIntersectingHorizontally( nodeRect, currentRect ) - && isRectIntersectingVertically( nodeRect, screenRect ) ) { - boolean swap = false; - if( nodeRect.y < currentRect.y ) { - swap = needSwapWithUpRect( upRect, nodeRect ); - } - if( swap ) { - upNode = node; - upRect = nodeRect; - } - } - } - return upNode; - } - - private Node findLowestFocusableNodeInScreen() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - XYRect screenRect = getUnscaledScreenRect(); - Node firstNode = null; - XYRect firstRect = null; - - for( int i = _navigationController._focusableNodes.size() - 1; i >= 0; i-- ) { - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 - || _navigationController.isFocusableDisabled( node ) ) { - continue; - } - if( isRectIntersectingVertically( nodeRect, screenRect ) ) { - boolean swap = false; - // Should select the lowest item in the screen that completely fits on screen - if( nodeRect.y + nodeRect.height < screenRect.y + screenRect.height ) { - swap = needSwapWithUpRect( firstRect, nodeRect ); - } - if( swap ) { - firstNode = node; - firstRect = nodeRect; - } - } - } - return firstNode; - } - - private Node findRightFocusableNode() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - if( _navigationController._currentFocusNode == null || _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ) == -1 ) - return findRightestFocusableNodeInScreen(); - - int index = _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ); - XYRect currentRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - Node rightNode = null; - XYRect rightRect = null; - - for( int i = 0; i < _navigationController._focusableNodes.size(); i++ ) { - if( i == index ) { - continue; - } - - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 - || _navigationController.isFocusableDisabled( node ) ) { - continue; - } - - if( isRectIntersectingHorizontally( nodeRect, currentRect ) ) { - boolean swap = false; - if( nodeRect.x == currentRect.x ) { - if( nodeRect.width == currentRect.width ) { - if( i > index ) { - return node; - } - } else if( nodeRect.width > currentRect.width ) { - if( rightNode == null ) { - swap = true; - } else { - if( nodeRect.x == rightRect.x ) { - if( nodeRect.width < rightRect.width ) { - swap = true; - } - } else if( nodeRect.x < rightRect.x ) { - swap = true; - } - } - } - } else if( nodeRect.x > currentRect.x ) { - if( rightNode == null ) { - swap = true; - } else { - if( nodeRect.x == rightRect.x ) { - if( nodeRect.width < rightRect.width ) { - swap = true; - } - } else if( nodeRect.x < rightRect.x ) { - swap = true; - } - } - } - if( swap ) { - rightNode = node; - rightRect = nodeRect; - } - } + throw new Error( "Invalid event type: " + _eventType ); } - - return rightNode; } - - private Node findRightestFocusableNodeInScreen() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - XYRect screenRect = getUnscaledScreenRect(); - Node firstNode = null; - XYRect firstRect = null; - - for( int i = 0; i < _navigationController._focusableNodes.size(); i++ ) { - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 - || _navigationController.isFocusableDisabled( node ) ) { - continue; - } - if( isRectIntersectingHorizontally( nodeRect, screenRect ) ) { - boolean swap = false; - - if( nodeRect.x >= screenRect.x ) { - if( firstNode == null ) { - swap = true; - } else { - if( nodeRect.x == firstRect.x ) { - if( nodeRect.width < firstRect.width ) { - swap = true; - } - } else if( nodeRect.x < firstRect.x ) { - swap = true; - } - } - } - if( swap ) { - firstNode = node; - firstRect = nodeRect; - } - } - } - return firstNode; - } - - private Node findLeftFocusableNode() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - if( _navigationController._currentFocusNode == null || _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ) == -1 ) - return findLeftestFocusableNodeInScreen(); - - int index = _navigationController._focusableNodes.indexOf( _navigationController._currentFocusNode ); - - XYRect currentRect = _navigationController._widgetFieldManager.getPosition( _navigationController._currentFocusNode ); - Node leftNode = null; - XYRect leftRect = null; - - for( int i = _navigationController._focusableNodes.size() - 1; i >= 0; i-- ) { - if( i == index ) { - continue; - } - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 - || _navigationController.isFocusableDisabled( node ) ) { - continue; - } - - if( isRectIntersectingHorizontally( nodeRect, currentRect ) ) { - boolean swap = false; - if( nodeRect.x == currentRect.x ) { - if( nodeRect.width == currentRect.width ) { - if( i < index ) { - return node; - } - } else if( nodeRect.width < currentRect.width ) { - if( leftNode == null ) { - swap = true; - } else { - if( nodeRect.x == leftRect.x ) { - if( nodeRect.width > leftRect.width ) { - swap = true; - } - } else if( nodeRect.x > leftRect.x ) { - swap = true; - } - } - } - } else if( nodeRect.x < currentRect.x ) { - if( leftNode == null ) { - swap = true; - } else { - if( nodeRect.x == leftRect.x ) { - if( nodeRect.width > leftRect.width ) { - swap = true; - } - } else if( nodeRect.x > leftRect.x ) { - swap = true; - } - } - } - if( swap ) { - leftNode = node; - leftRect = nodeRect; - } - } - } - return leftNode; - } - - private Node findLeftestFocusableNodeInScreen() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - XYRect screenRect = getUnscaledScreenRect(); - Node firstNode = null; - XYRect firstRect = null; - - for( int i = _navigationController._focusableNodes.size() - 1; i >= 0; i-- ) { - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 ) { - continue; - } - if( _navigationController.isFocusableDisabled( node ) ) { - continue; - } - if( isRectIntersectingHorizontally( nodeRect, screenRect ) ) { - boolean swap = false; - - if( nodeRect.x < screenRect.x + screenRect.width ) { - if( firstNode == null ) { - swap = true; - } else { - if( nodeRect.x == firstRect.x ) { - if( nodeRect.width > firstRect.width ) { - swap = true; - } - } else if( nodeRect.x > firstRect.x ) { - swap = true; - } - } - } - if( swap ) { - firstNode = node; - firstRect = nodeRect; - } - } - } - return firstNode; - } - - private Node findHighestFocusableNodeInScreen() { - - if( _navigationController._focusableNodes == null || _navigationController._focusableNodes.size() == 0 ) - return null; - - XYRect screenRect = getUnscaledScreenRect(); - Node firstNode = null; - XYRect firstRect = null; - - for( int i = 0; i < _navigationController._focusableNodes.size(); i++ ) { - Node node = (Node) _navigationController._focusableNodes.elementAt( i ); - XYRect nodeRect = _navigationController._widgetFieldManager.getPosition( node ); - - if( nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0 - || _navigationController.isFocusableDisabled( node ) ) { - continue; - } - if( isRectIntersectingVertically( nodeRect, screenRect ) ) { - boolean swap = false; - if( nodeRect.y >= screenRect.y ) { - swap = needSwapWithDownRect( firstRect, nodeRect ); - } - if( swap ) { - firstNode = node; - firstRect = nodeRect; - } - } - } - return firstNode; - } - - private boolean isRectIntersectingVertically( final XYRect rect1, final XYRect rect2 ) { - if( rect1 == null || rect2 == null ) - return false; - if( rect2.x <= rect1.x && ( rect2.x + rect2.width - 1 ) >= rect1.x ) - return true; - return ( rect2.x >= rect1.x && rect2.x <= ( rect1.x + rect1.width - 1 ) ); - } - - private boolean isRectIntersectingHorizontally( final XYRect rect1, final XYRect rect2 ) { - if( rect1 == null || rect2 == null ) - return false; - if( rect2.y <= rect1.y && ( rect2.y + rect2.height - 1 ) >= rect1.y ) - return true; - return ( rect2.y >= rect1.y && rect2.y <= ( rect1.y + rect1.height - 1 ) ); - } - - private boolean needSwapWithUpRect( final XYRect upRect, final XYRect checkedRect ) { - if( upRect == null ) - return true; - if( checkedRect.y == upRect.y && checkedRect.height > upRect.height ) - return true; - return ( checkedRect.y > upRect.y ); - } - - private boolean needSwapWithUpRectInPriority( final XYRect upRect, final XYRect checkedRect ) { - if( upRect == null ) - return true; - if( checkedRect.y == upRect.y && checkedRect.height >= upRect.height ) - return true; - return ( checkedRect.y > upRect.y ); - } - - private boolean needSwapWithDownRect( final XYRect downRect, final XYRect checkedRect ) { - if( downRect == null ) - return true; - if( checkedRect.y == downRect.y && checkedRect.height < downRect.height ) - return true; - return ( checkedRect.y < downRect.y ); - } - - private boolean needSwapWithDownRectInPriority( final XYRect downRect, final XYRect checkedRect ) { - if( downRect == null ) - return true; - if( checkedRect.y == downRect.y && checkedRect.height <= downRect.height ) - return true; - return ( checkedRect.y < downRect.y ); + // Call back from NavigationUiDispatcherEvent + private void handleDirection( int direction, int delta ) { + _navigationController.triggerNavigationDirection( direction, delta ); } - - private XYRect getUnscaledScreenRect() { - XYRect screenRect = new XYRect( _navigationController._widgetFieldManager.getHorizontalScroll(), - _navigationController._widgetFieldManager.getVerticalScroll(), - _navigationController._widgetFieldManager.getWidth(), - _navigationController._widgetFieldManager.getHeight() ); - return _navigationController._widgetFieldManager.unscaleRect( screenRect ); - } - } \ No newline at end of file diff --git a/framework/src/js/navmode.js b/framework/src/js/navmode.js new file mode 100644 index 0000000..ce194cd --- /dev/null +++ b/framework/src/js/navmode.js @@ -0,0 +1 @@ +(function(){navigationController={SAFE_MARGIN:30,SUPPRESS_NAVIGATION_INPUT_TYPES:"|checkbox|radio|button|",AUTO_FOCUS_INPUT_TYPES:"|color|date|month|time|week|email|number|password|search|text|url|tel|",SCROLLABLE_INPUT_TYPES:"|text|password|email|search|tel|number|url|",REQUIRE_CLICK_INPUT_TYPES:"|file|",querySelector:"textarea:not([x-blackberry-focusable=false]),a:not([x-blackberry-focusable=false]),input:not([x-blackberry-focusable=false]), select:not([x-blackberry-focusable=false]), iframe:not([x-blackberry-focusable=false]), button:not([x-blackberry-focusable=false]), [x-blackberry-focusable=true]",DOWN:3,UP:2,RIGHT:0,LEFT:1,domDirty:false,currentFocused:null,priorFocusedId:"",lastDirection:null,focusableNodes:[],zoomScale:null,currentDirection:null,delta:null,virtualHeight:null,virtualWidth:null,verticalScroll:null,horizontalScroll:null,height:null,width:null,rangeNavigationOn:false,lastCaretPosition:0,initialize:function(a){navigationController.changeInputNodeTypes(["date","month","time","datetime","datetime-local"]);navigationController.assignScrollData(a);navigationController.focusableNodes=navigationController.getFocusableElements();navigationController.SAFE_MARGIN=navigationController.height/10;if(navigationController.device.isBB5()){addEventListener("DOMNodeInsertedIntoDocument",function(){navigationController.domDirty=true},true);addEventListener("DOMNodeRemovedFromDocument",function(){navigationController.domDirty=true},true)}var b=document.body.querySelectorAll("[x-blackberry-initialFocus=true]");if(b.length===0){navigationController.setRimFocus(navigationController.findHighestFocusableNodeInScreen())}else{var c=b[0];if(!navigationController.isValidFocusableNode(c)){c=null}if(c!==null){var d=navigationController.determineBoundingRect(c);var e={element:c,rect:d.rect,scrollableParent:d.scrollableParent};navigationController.setRimFocus(e)}else{navigationController.setRimFocus(navigationController.findHighestFocusableNodeInScreen())}}},changeInputNodeTypes:function(a){var b,c,d,e;for(b=0;b=0},isBB6:function(){return navigator.appVersion.indexOf("6.0.0")>=0},isBB7:function(){return navigator.appVersion.indexOf("7.0.0")>=0}},assignScrollData:function(a){navigationController.currentDirection=a.direction;navigationController.delta=a.delta;navigationController.zoomScale=a.zoomScale;navigationController.virtualHeight=a.virtualHeight;navigationController.virtualWidth=a.virtualWidth;navigationController.verticalScroll=a.verticalScroll;navigationController.horizontalScroll=a.horizontalScroll;navigationController.height=a.height;navigationController.width=a.width},getDirection:function(){return navigationController.currentDirection},getFocus:function(){if(navigationController.currentFocused===null){return null}else{return navigationController.currentFocused.element.getAttribute("id")}},setFocus:function(a){if(a.length===0){navigationController.focusOut();return}var b=null;b=document.getElementById(a);if(b!==null){if(!navigationController.isValidFocusableNode(b)){b=null}}if(b!==null){var c=navigationController.determineBoundingRect(b);var d={element:b,rect:c.rect,scrollableParent:c.scrollableParent};navigationController.setRimFocus(d)}},getPriorFocus:function(){return navigationController.priorFocusedId},isScrollableElement:function(a){if(a.tagName=="TEXTAREA"){return true}if(a.tagName=="INPUT"&&a.hasAttribute("type")){var b=a.getAttribute("type").toLowerCase();return navigationController.SCROLLABLE_INPUT_TYPES.indexOf(b)>0}return false},onScroll:function(data){navigationController.assignScrollData(data);if(!navigationController.device.isBB5()||navigationController.domDirty){navigationController.focusableNodes=navigationController.getFocusableElements();navigationController.domDirty=false}if(navigationController.currentFocused){var element=navigationController.currentFocused.element;if(navigationController.isScrollableElement(element)){var caretPos=element.selectionStart;if(navigationController.currentDirection==navigationController.RIGHT||navigationController.currentDirection==navigationController.DOWN){if(navigationController.lastCaretPosition0){navigationController.lastCaretPosition=caretPos;return}}}}if(navigationController.currentDirection===navigationController.DOWN){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onDown")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onDown"));return}else{navigationController.handleDirectionDown()}}else if(navigationController.currentDirection===navigationController.UP){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onUp")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onUp"));return}else{navigationController.handleDirectionUp()}}else if(navigationController.currentDirection===navigationController.RIGHT){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onRight")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onRight"));return}else{navigationController.handleDirectionRight()}}else if(navigationController.currentDirection===navigationController.LEFT){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onLeft")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onLeft"));return}else{navigationController.handleDirectionLeft()}}navigationController.lastDirection=navigationController.currentDirection},onTrackpadDown:function(){},onTrackpadUp:function(){if(navigationController.currentFocused===null){return}try{var a=document.createEvent("MouseEvents");a.initMouseEvent("mouseup",true,true,window,0,navigationController.currentFocused.rect.x,navigationController.currentFocused.rect.y,1,1,false,false,false,false,0,null);navigationController.currentFocused.element.dispatchEvent(a);navigationController.onTrackpadClick()}catch(b){}},onTrackpadClick:function(){if(!navigationController.currentFocused){return}if(navigationController.isRangeControl(navigationController.currentFocused.element)){navigationController.rangeNavigationOn=!navigationController.rangeNavigationOn}var a=navigationController.currentFocused,b=document.createEvent("MouseEvents"),c,d;b.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,0,null);c=!a.element.dispatchEvent(b);if(!c){if(typeof (navigationController[a.element.tagName]==="function")){navigationController[a.element.tagName](a.element)}}},INPUT:function(a){navigationController.onInput=function(b){var c=document.createEvent("HTMLEvents"),d=false;if(a.value!==b){a.value=b;d=true}if(d){c.initEvent("change",true,true);a.dispatchEvent(c)}};var b=a.attributes.getNamedItem("type").value;switch(b){case"x-blackberry-date":case"x-blackberry-datetime":case"x-blackberry-datetime-local":case"x-blackberry-month":case"x-blackberry-time":navigationController.handleInputDateTime(b.substring(b.lastIndexOf("-")+1),{value:a.value,min:a.min,max:a.max,step:a.step},navigationController.onInput);break;case"color":if(navigationController.device.isBB5()||navigationController.device.isBB6()){var c=a.value;if(c===""){c="000000"}navigationController.handleInputColor(c,navigationController.onInput)}break;default:break}},SELECT:function(a){function b(a){var b=[],c=a.options,d=0,e,f="",g;for(d;dnavigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.y+e.height<=a.y+d){navigationController.focusOut()}}navigationController.scrollDown()}},handleDirectionUp:function(){var a=navigationController.getUnscaledScreenRect();var b=navigationController.findUpFocusableNode();if(b!=null){var c=b.rect;if(c.y+c.height>a.y){navigationController.setRimFocus(b);return}}var d=a.y;if(d>navigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.y>a.y-d+a.height){navigationController.focusOut()}}navigationController.scrollUp()}},isRangeControl:function(a){if(a.type=="range"){return true}return false},handleRangeSliderMovement:function(a){var b=navigationController.currentFocused.element;var c=b.value;switch(a){case"r":if(c1){b.value--}break;default:console.log("Impossible")}},handleDirectionRight:function(){if(navigationController.currentFocused!=null&&navigationController.isRangeControl(navigationController.currentFocused.element)&&navigationController.rangeNavigationOn){navigationController.handleRangeSliderMovement("r")}else{var a=navigationController.getUnscaledScreenRect();var b=navigationController.findRightFocusableNode();if(b!=null){var c=b.rect;if(c.x<=a.x+a.width){navigationController.setRimFocus(b);return}}var d=navigationController.unscaleValue(navigationController.virtualWidth)-a.x-a.width;if(d>navigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.x+e.width<=a.x+d){navigationController.focusOut()}}navigationController.scrollRight()}}},handleDirectionLeft:function(){if(navigationController.currentFocused!=null&&navigationController.isRangeControl(navigationController.currentFocused.element)&&navigationController.rangeNavigationOn){navigationController.handleRangeSliderMovement("l")}else{var a=navigationController.getUnscaledScreenRect();var b=navigationController.findLeftFocusableNode();if(b!=null){var c=b.rect;if(c.x+c.width>a.x){navigationController.setRimFocus(b);return}}var d=a.x;if(d>navigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.x>a.x-d+a.width){navigationController.focusOut()}}navigationController.scrollLeft()}}},findHighestFocusableNodeInScreen:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a=navigationController.getUnscaledScreenRect();var b=null;var c=null;var d=navigationController.focusableNodes.length;for(var e=0;e=a.y){h=navigationController.needSwapWithDownRect(c,g)}if(h){b=f;c=g}}}return b},findLowestFocusableNodeInScreen:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a=navigationController.getUnscaledScreenRect();var b=null;var c=null;var d=navigationController.focusableNodes.length;for(var e=d-1;e>=0;e--){var f=navigationController.focusableNodes[e];var g=f.rect;if(g==null||g.width==0||g.height==0){continue}if(navigationController.isRectIntersectingVertically(g,a)){var h=false;if(g.y+g.height=0;e--){var f=navigationController.focusableNodes[e];var g=f.rect;if(g==null||g.width==0||g.height==0){continue}if(navigationController.isRectIntersectingHorizontally(g,a)){var h=false;if(g.xc.width){h=true}}else if(g.x>c.x){h=true}}}if(h){b=f;c=g}}}return b},findRightmostFocusableNodeInScreen:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a=navigationController.getUnscaledScreenRect();var b=null;var c=null;var d=navigationController.focusableNodes.length;for(var e=0;e=a.x){if(b==null){h=true}else{if(g.x==c.x){if(g.widtha){return h}}else if(i.height>b.height){j=navigationController.needSwapWithDownRectInPriority(f,i)}}else if(i.y>b.y){j=navigationController.needSwapWithDownRectInPriority(f,i)}if(j){e=h;f=i}}else if(!navigationController.isRectIntersectingHorizontally(i,b)&&navigationController.isRectIntersectingVertically(i,c)){var j=false;if(i.y>b.y){j=navigationController.needSwapWithDownRect(f,i)}if(j){e=h;f=i}}}return e},findUpFocusableNode:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a;if(navigationController.currentFocused!=null)a=navigationController.indexOf(navigationController.currentFocused);else return navigationController.findLowestFocusableNodeInScreen();if(a==-1){return navigationController.findLowestFocusableNodeInScreen()}var b=navigationController.currentFocused.rect;var c=null;var d=null;var e=navigationController.getUnscaledScreenRect();var f=navigationController.focusableNodes.length;for(var g=f-1;g>=0;g--){if(g==a){continue}var h=navigationController.focusableNodes[g];var i=h.rect;if(i==null||i.width==0||i.height==0){continue}if(navigationController.isRectIntersectingVertically(i,b)){var j=false;if(i.y==b.y){if(i.height==b.height){if(g=0;f--){if(f==a){continue}var g=navigationController.focusableNodes[f];var h=g.rect;if(h==null||h.width==0||h.height==0){continue}if(navigationController.isRectIntersectingHorizontally(h,b)){var i=false;if(h.x==b.x){if(h.width==b.width){if(fd.width){i=true}}else if(h.x>d.x){i=true}}}}else if(h.xd.width){i=true}}else if(h.x>d.x){i=true}}}if(i){c=g;d=h}}}return c},findRightFocusableNode:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a;if(navigationController.currentFocused!=null)a=navigationController.indexOf(navigationController.currentFocused);else return navigationController.findRightmostFocusableNodeInScreen();if(a==-1){return navigationController.findRightmostFocusableNodeInScreen()}var b=navigationController.currentFocused.rect;var c=null;var d=null;var e=navigationController.focusableNodes.length;for(var f=0;fa){return g}}else if(h.width>b.width){if(c==null){i=true}else{if(h.x==d.x){if(h.widthb.x){if(c==null){i=true}else{if(h.x==d.x){if(h.width=a.x)return true;return b.x>=a.x&&b.x<=a.x+a.width-1},needSwapWithDownRectInPriority:function(a,b){if(a==null)return true;if(b.y==a.y&&b.height<=a.height)return true;return b.y=a.y)return true;return b.y>=a.y&&b.y<=a.y+a.height-1},needSwapWithDownRect:function(a,b){if(a==null)return true;if(b.y==a.y&&b.height=a.height)return true;return b.y>a.y},needSwapWithUpRect:function(a,b){if(a==null)return true;if(b.y==a.y&&b.height>a.height)return true;return b.y>a.y},getUnscaledScreenRect:function(){var a={y:navigationController.verticalScroll,x:navigationController.horizontalScroll,height:navigationController.height,width:navigationController.width};return navigationController.unscaleRect(a)},isValidFocusableNode:function(a){if(a==null)return false;if(navigationController.indexOf({element:a})==-1){return false}var b=navigationController.determineBoundingRect(a);return!(b==null||b.width==0||b.height==0)},isAutoFocus:function(a){if(a.element.tagName=="INPUT"){if(a.element.hasAttribute("type")){var b=a.element.getAttribute("type").toLowerCase();return navigationController.AUTO_FOCUS_INPUT_TYPES.indexOf(b)>0}}if(a.element.tagName=="TEXTAREA"){return true}return false},scrollToRect:function(a){var b=navigationController.verticalScroll;var c=b;if(a.yb+navigationController.height){c=Math.min(a.y+a.height-navigationController.height,navigationController.virtualHeight-navigationController.height)}var d=navigationController.horizontalScroll;var e=d;if(a.width>=navigationController.width){e=Math.max(a.x,0)}else if(a.xd+navigationController.width){e=Math.min(a.x+a.width-navigationController.width,navigationController.virtualWidth-navigationController.width)}if(e!=d||c!=b){navigationController.scrollXY(e,c)}},scrollDown:function(){var a=Math.min(navigationController.verticalScroll+navigationController.scaleValue(navigationController.SAFE_MARGIN),navigationController.virtualHeight-navigationController.height);navigationController.scrollY(a)},scrollUp:function(){var a=Math.max(navigationController.verticalScroll-navigationController.scaleValue(navigationController.SAFE_MARGIN),0);navigationController.scrollY(a)},scrollRight:function(){var a=Math.min(navigationController.horizontalScroll+navigationController.scaleValue(navigationController.SAFE_MARGIN),navigationController.virtualWidth-navigationController.width);navigationController.scrollXY(a,navigationController.verticalScroll)},scrollLeft:function(){var a=Math.max(navigationController.horizontalScroll-navigationController.scaleValue(navigationController.SAFE_MARGIN),0);navigationController.scrollXY(a,navigationController.verticalScroll)},scaleRect:function(a){var b={y:navigationController.scaleValue(a.y),x:navigationController.scaleValue(a.x),height:navigationController.scaleValue(a.height),width:navigationController.scaleValue(a.width)};return b},scaleValue:function(a){return Math.round(a*navigationController.zoomScale)},unscaleValue:function(a){return Math.round(a/navigationController.zoomScale)},unscaleRect:function(a){var b={y:navigationController.unscaleValue(a.y),x:navigationController.unscaleValue(a.x),height:navigationController.unscaleValue(a.height),width:navigationController.unscaleValue(a.width)};return b},scrollXY:function(a,b){window.scrollTo(navigationController.unscaleValue(a),navigationController.unscaleValue(b))},scrollX:function(a){window.scrollTo(navigationController.unscaleValue(a),window.pageYOffset)},scrollY:function(a){window.scrollTo(window.pageXOffset,navigationController.unscaleValue(a))}};bbNav={init:function(){if(window.top===window.self){var a={direction:3,delta:1,zoomScale:1,virtualHeight:screen.height,virtualWidth:screen.width,verticalScroll:0,horizontalScroll:0,height:screen.height,width:screen.width};blackberry.focus.onScroll=navigationController.onScroll;blackberry.focus.onTrackpadDown=navigationController.onTrackpadDown;blackberry.focus.onTrackpadUp=navigationController.onTrackpadUp;blackberry.focus.getDirection=navigationController.getDirection;blackberry.focus.getFocus=navigationController.getFocus;blackberry.focus.getPriorFocus=navigationController.getPriorFocus;blackberry.focus.setFocus=navigationController.setFocus;blackberry.focus.focusOut=navigationController.focusOut;navigationController.initialize(a);navigationController.handleSelect=blackberry.ui.dialog.selectAsync;navigationController.handleInputDateTime=blackberry.ui.dialog.dateTimeAsync;navigationController.handleInputColor=blackberry.ui.dialog.colorPickerAsync}}};addEventListener("load",bbNav.init,false)})() \ No newline at end of file diff --git a/framework/src/js/navmode_uncompressed.js b/framework/src/js/navmode_uncompressed.js new file mode 100644 index 0000000..90a3e4f --- /dev/null +++ b/framework/src/js/navmode_uncompressed.js @@ -0,0 +1,1445 @@ +/* + * Copyright 2010-2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function() { +navigationController = { + + SAFE_MARGIN : 30, + SUPPRESS_NAVIGATION_INPUT_TYPES : '|checkbox|radio|button|', + AUTO_FOCUS_INPUT_TYPES : '|color|date|month|time|week|email|number|password|search|text|url|tel|', + SCROLLABLE_INPUT_TYPES : '|text|password|email|search|tel|number|url|', + REQUIRE_CLICK_INPUT_TYPES : '|file|', + querySelector : 'textarea:not([x-blackberry-focusable=false]),a:not([x-blackberry-focusable=false]),input:not([x-blackberry-focusable=false]), select:not([x-blackberry-focusable=false]), iframe:not([x-blackberry-focusable=false]), button:not([x-blackberry-focusable=false]), [x-blackberry-focusable=true]', + + DOWN : 3, + UP : 2, + RIGHT : 0, + LEFT : 1, + + domDirty : false, // This is for use with BB5 only + currentFocused : null, + priorFocusedId : '', + lastDirection : null, + + focusableNodes : [], + + // Scroll Data + zoomScale : null, + currentDirection : null, + delta : null, + virtualHeight : null, + virtualWidth : null, + verticalScroll : null, + horizontalScroll : null, + height : null, + width : null, + rangeNavigationOn : false, + lastCaretPosition : 0, + + /* Sets the top mose focusable item as selected on first load of the page */ + initialize : function(data) { + // Prepend 'x-blackberry-' in front of these types to prevent browser from automatically displaying its UI on focus + navigationController.changeInputNodeTypes(["date", "month", "time", "datetime", "datetime-local"]); + + // Initialize the scroll information + navigationController.assignScrollData(data); + navigationController.focusableNodes = navigationController.getFocusableElements(); + + // Figure out our safe margins + /* + * if (navigationController.device.isBB5() || + * navigationController.device.isBB6()) { + * navigationController.SAFE_MARGIN = 30; } else { + * navigationController.SAFE_MARGIN = 50; } + */ + navigationController.SAFE_MARGIN = navigationController.height / 10; + + /* + * Set our DOM Mutation events if it is BB5 to mark the DOM as dirty if + * any elements were inserted or removed from the DOM + */ + if (navigationController.device.isBB5()) { + addEventListener("DOMNodeInsertedIntoDocument", function() { + navigationController.domDirty = true; + }, true); + + addEventListener("DOMNodeRemovedFromDocument", function() { + navigationController.domDirty = true; + }, true); + } + + // Find our first focusable item + var initialItems = document.body.querySelectorAll('[x-blackberry-initialFocus=true]'); + if (initialItems.length === 0) { + navigationController.setRimFocus(navigationController.findHighestFocusableNodeInScreen()); + } else { + var nextFocusNode = initialItems[0]; + if (!navigationController.isValidFocusableNode(nextFocusNode)) { + nextFocusNode = null; + } + if (nextFocusNode !== null) { + var result = navigationController.determineBoundingRect(nextFocusNode); + var bounds = { + 'element' : nextFocusNode, + 'rect' : result.rect, + 'scrollableParent' : result.scrollableParent + }; + navigationController.setRimFocus(bounds); + } else { // Get the top most node + navigationController.setRimFocus(navigationController.findHighestFocusableNodeInScreen()); + } + } + }, + + changeInputNodeTypes : function(inputTypes) { + var i, + j, + selector, + nodes; + + for(i = 0; i < inputTypes.length; i++) { + selector = "input[type=" + inputTypes[i] + "]"; + nodes = document.querySelectorAll(selector); + + for(j = 0; j < nodes.length; j++) { + nodes[j].type = "x-blackberry-" + inputTypes[i]; + } + } + }, + + // Contains all device information + device : { + // Determine if this browser is BB5 + isBB5 : function() { + return navigator.appVersion.indexOf('5.0.0') >= 0; + }, + + // Determine if this browser is BB6 + isBB6 : function() { + return navigator.appVersion.indexOf('6.0.0') >= 0; + }, + + // Determine if this browser is BB7 + isBB7 : function() { + return navigator.appVersion.indexOf('7.0.0') >= 0; + } + + }, + + // Assigns all the scrolling data + assignScrollData : function(data) { + navigationController.currentDirection = data.direction; + navigationController.delta = data.delta; + navigationController.zoomScale = data.zoomScale; + navigationController.virtualHeight = data.virtualHeight; + navigationController.virtualWidth = data.virtualWidth; + navigationController.verticalScroll = data.verticalScroll; + navigationController.horizontalScroll = data.horizontalScroll; + navigationController.height = data.height; + navigationController.width = data.width; + }, + + /* returns the current scrolling direction */ + getDirection : function() { + return navigationController.currentDirection; + }, + + /* Returns the current focused element's id */ + getFocus : function() { + if (navigationController.currentFocused === null) { + return null; + } else { + return navigationController.currentFocused.element.getAttribute('id'); + } + }, + + /* Set's the focus to an element with the supplied id */ + setFocus : function(id) { + if (id.length === 0) { + navigationController.focusOut(); + return; + } + var nextFocusNode = null; + nextFocusNode = document.getElementById(id); + if (nextFocusNode !== null) { + if (!navigationController.isValidFocusableNode(nextFocusNode)) { + nextFocusNode = null; + } + } + if (nextFocusNode !== null) { + var result = navigationController.determineBoundingRect(nextFocusNode); + var bounds = { + 'element' : nextFocusNode, + 'rect' : result.rect, + 'scrollableParent' : result.scrollableParent + }; + navigationController.setRimFocus(bounds); + } + }, + + /* Returns the previously focused element's id */ + getPriorFocus : function() { + return navigationController.priorFocusedId; + }, + + isScrollableElement : function(element) { + if (element.tagName == 'TEXTAREA') { + return true; + } + if (element.tagName == 'INPUT' && element.hasAttribute('type')) { + var type = element.getAttribute('type').toLowerCase(); + return navigationController.SCROLLABLE_INPUT_TYPES.indexOf(type) > 0; + } + return false; + }, + + /* Handle scrolling the focus in the proper direction */ + onScroll : function(data) { + navigationController.assignScrollData(data); + + // If it is BB5 then don't re-calculate the bounding rects unless + // the DOM is dirty + // it's too much of a performance hit on BB5 to re-calculate each + // scroll + if (!navigationController.device.isBB5() || navigationController.domDirty) { + navigationController.focusableNodes = navigationController.getFocusableElements(); + navigationController.domDirty = false; + } + + // Logic to handle cursor movement in scrollable controls (e.g. text input and textarea), + // Only handle scrolling with cursor is at the beginning or end position + if (navigationController.currentFocused) { + var element = navigationController.currentFocused.element; + if (navigationController.isScrollableElement(element)) { + var caretPos = element.selectionStart; + if (navigationController.currentDirection == navigationController.RIGHT || + navigationController.currentDirection == navigationController.DOWN) { + if (navigationController.lastCaretPosition < element.value.length-1) { + navigationController.lastCaretPosition = caretPos; + return; + } + } else if (navigationController.currentDirection == navigationController.LEFT || + navigationController.currentDirection == navigationController.UP) { + if (navigationController.lastCaretPosition > 0) { + navigationController.lastCaretPosition = caretPos; + return; + } + } + } + } + + // Determine our direction and scroll + if (navigationController.currentDirection === navigationController.DOWN) { + if (navigationController.currentFocused + && navigationController.currentFocused.element.hasAttribute('x-blackberry-onDown')) { + eval(navigationController.currentFocused.element.getAttribute('x-blackberry-onDown')); + return; + } else { + navigationController.handleDirectionDown(); + } + } else if (navigationController.currentDirection === navigationController.UP) { + if (navigationController.currentFocused + && navigationController.currentFocused.element.hasAttribute('x-blackberry-onUp')) { + eval(navigationController.currentFocused.element.getAttribute('x-blackberry-onUp')); + return; + } else { + navigationController.handleDirectionUp(); + } + } else if (navigationController.currentDirection === navigationController.RIGHT) { + if (navigationController.currentFocused + && navigationController.currentFocused.element.hasAttribute('x-blackberry-onRight')) { + eval(navigationController.currentFocused.element.getAttribute('x-blackberry-onRight')); + return; + } else { + navigationController.handleDirectionRight(); + } + } else if (navigationController.currentDirection === navigationController.LEFT) { + if (navigationController.currentFocused + && navigationController.currentFocused.element.hasAttribute('x-blackberry-onLeft')) { + eval(navigationController.currentFocused.element.getAttribute('x-blackberry-onLeft')); + return; + } else { + navigationController.handleDirectionLeft(); + } + } + + navigationController.lastDirection = navigationController.currentDirection; + }, + + /* Handle the press from the trackpad */ + onTrackpadDown : function() { + }, + + /* Handle the "release" of the press from the trackpad */ + onTrackpadUp : function() { + if (navigationController.currentFocused === null) { + return; + } + + try { + // Now send the mouseup DOM event + var mouseup = document.createEvent("MouseEvents"); + mouseup.initMouseEvent("mouseup", true, true, window, 0, navigationController.currentFocused.rect.x, + navigationController.currentFocused.rect.y, 1, 1, false, false, false, false, 0, null); + navigationController.currentFocused.element.dispatchEvent(mouseup); + navigationController.onTrackpadClick(); + } catch (e) { + // TODO: the last line sometimes causes an exception in 5.0 only, could not figure out why + // do nothing + } + }, + + onTrackpadClick : function() { + if (!navigationController.currentFocused) { + return; + } + if (navigationController.isRangeControl(navigationController.currentFocused.element)) { + navigationController.rangeNavigationOn = !navigationController.rangeNavigationOn; + } + + var focus = navigationController.currentFocused, //Closure the current focus + click = document.createEvent("MouseEvents"), + cancelled, + nativeInfo; + + // Now send the DOM event and see if any listeners preventDefault() + //click.initMouseEvent("click", true, true, window, 0, navigationController.currentFocused.rect.x, navigationController.currentFocused.rect.y, 1, 1, false, false, false, false, 0, null); + click.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + cancelled = !focus.element.dispatchEvent(click); + + if(!cancelled) { + //By convention we'll define a handler for each tag with a native UI at navigationController.tagName + if(typeof(navigationController[focus.element.tagName] === "function")) { + navigationController[focus.element.tagName](focus.element); + } + } + }, + + INPUT : function(htmlElem) { + navigationController.onInput = function(value) { + var change = document.createEvent("HTMLEvents"), + fireChange = false; + + if(htmlElem.value !== value) { + htmlElem.value = value; + fireChange = true; + } + + if(fireChange) { + change.initEvent("change", true, true); + htmlElem.dispatchEvent(change); + } + }; + + var type = htmlElem.attributes.getNamedItem("type").value; + switch(type) { + case "x-blackberry-date" : + case "x-blackberry-datetime" : + case "x-blackberry-datetime-local" : + case "x-blackberry-month" : + case "x-blackberry-time" : navigationController.handleInputDateTime( + type.substring(type.lastIndexOf("-") + 1), + { + value : htmlElem.value, + min : htmlElem.min, + max : htmlElem.max, + step : htmlElem.step + }, + navigationController.onInput + ); + break; + case "color" : + if (navigationController.device.isBB5() || navigationController.device.isBB6()) { + var value = htmlElem.value; + if (value === "") { + value = "000000"; + } + navigationController.handleInputColor( + value, + navigationController.onInput + ); + } + break; + default: break; //no special handling + } + }, + + SELECT: function(htmlElem) { + //We'll stick our event handler at on[tagName] + navigationController.onSELECT = function(evtData) { + var i, + change = document.createEvent("HTMLEvents"), + newSelection = [], + fireChange = false; + + //Initialize to all false + for(i = 0; i < htmlElem.options.length; i++) { + newSelection.push(false); + } + + //flip the selected items to true + for(i = 0; i < evtData.length; i++) { + newSelection[evtData[i]] = true; + } + + // change state of multi select to match selection array + // set changed event to fire only if the selection state is + // different + for(i = 0; i < newSelection.length; i++) { + if(newSelection[i] !== htmlElem.options.item(i).selected) { + htmlElem.options.item(i).selected = newSelection[i]; + fireChange = true; + } + } + + if(fireChange) { + change.initEvent("change", true, true); + htmlElem.dispatchEvent(change); + } + }; + + function getSelectChoices(htmlElem) { + var opts = [], + optionNodes = htmlElem.options, + i = 0, + currentOption, + currentGroup = "", + nodeGroup; + + for(i; i < optionNodes.length; i++) { + currentOption = optionNodes.item(i); + nodeGroup = (currentOption.parentNode.tagName === "OPTGROUP") ? currentOption.parentNode.label : ""; + + if(currentGroup !== nodeGroup) { + currentGroup = nodeGroup; + + opts.push( + { + "label" : currentGroup, + "enabled" : false, + "selected" : false, + "type" : "group" + } + ); + } + + opts.push( + { + "label" : currentOption.text, + "enabled" : currentOption.disabled || (currentOption.disabled == false), + "selected" : currentOption.selected || (currentOption.selected == true), + "type" : "option" + } + ); + } + + return opts; + }; + + navigationController.handleSelect( + typeof(htmlElem.attributes.multiple) !== "undefined" ? true : false, + getSelectChoices(htmlElem), + navigationController.onSELECT + ); + }, + + /* See if the passed in element is still in our focusable list */ + indexOf : function(node) { + var length = navigationController.focusableNodes.length; + for ( var i = 0; i < length; i++) { + if (navigationController.focusableNodes[i].element == node.element) + return i; + } + return -1; + }, + + // Support function for scrolling down + handleDirectionDown : function() { + var screenRect = navigationController.getUnscaledScreenRect(); + var node = navigationController.findDownFocusableNode(); + + if (node != null) { + var nodeRect = node.rect; + if (nodeRect.y <= (screenRect.y + screenRect.height /* + navigationController.SAFE_MARGIN */)) { + navigationController.setRimFocus(node); + return; + } + } + + // Only scroll down the screen when there is more content underneath + var screenVerticalDelta = navigationController.unscaleValue(navigationController.virtualHeight) - screenRect.y + - screenRect.height; + if (screenVerticalDelta > navigationController.SAFE_MARGIN) { + screenVerticalDelta = navigationController.SAFE_MARGIN; + } + + if (screenVerticalDelta > 0) { + if (navigationController.currentFocused != null) { + // If current focused node is out of screen, focus out + var currentNodeRect = navigationController.currentFocused.rect; + if (currentNodeRect.y + currentNodeRect.height <= screenRect.y + screenVerticalDelta) { + navigationController.focusOut(); + } + } + navigationController.scrollDown(); + } + }, + + // Support function for scrolling up + handleDirectionUp : function() { + var screenRect = navigationController.getUnscaledScreenRect(); + var node = navigationController.findUpFocusableNode(); + if (node != null) { + var nodeRect = node.rect; + if ((nodeRect.y + nodeRect.height) > (screenRect.y /* - navigationController.SAFE_MARGIN */)) { + navigationController.setRimFocus(node); + return; + } + } + // Only scroll down the screen when there is more content above + var screenVerticalDelta = screenRect.y; + if (screenVerticalDelta > navigationController.SAFE_MARGIN) { + screenVerticalDelta = navigationController.SAFE_MARGIN; + } + if (screenVerticalDelta > 0) { + if (navigationController.currentFocused != null) { + // If current focused node is out of screen, focus out. + var currentNodeRect = navigationController.currentFocused.rect; + if (currentNodeRect.y > screenRect.y - screenVerticalDelta + screenRect.height) { + navigationController.focusOut(); + } + } + navigationController.scrollUp(); + } + }, + + //determines whether an input control is of the "range" type + isRangeControl : function(inputControl) { + if (inputControl.type == "range") { + return true; + } + return false; + }, + + //Support function for handling the slider movement of the range input control in navigation mode + handleRangeSliderMovement : function(direction) { + var currentNode = navigationController.currentFocused.element; + var currentValue = currentNode.value; + switch (direction) { + case 'r': //scroll right, increment position + if (currentValue < currentNode.clientWidth) { + currentNode.value ++; + } + break; + case 'l': //scroll left, decrement position + if (currentValue > 1) { + currentNode.value --; + } + break; + default: + console.log("Impossible"); + } + }, + + // Support function for scrolling right + handleDirectionRight : function() { + if (navigationController.currentFocused != null && + navigationController.isRangeControl(navigationController.currentFocused.element) && + navigationController.rangeNavigationOn) { + navigationController.handleRangeSliderMovement('r'); + } else { //we are not on a range control in navigation mode + var screenRect = navigationController.getUnscaledScreenRect(); + var node = navigationController.findRightFocusableNode(); + if (node != null) { + var nodeRect = node.rect; + if (nodeRect.x <= (screenRect.x + screenRect.width /* + navigationController.SAFE_MARGIN */)) { + navigationController.setRimFocus(node); + return; + } + } + // Only scroll down the screen when there is more content to the right. + var screenHorizontalDelta = navigationController.unscaleValue(navigationController.virtualWidth) - screenRect.x + - screenRect.width; + if (screenHorizontalDelta > navigationController.SAFE_MARGIN) { + screenHorizontalDelta = navigationController.SAFE_MARGIN; + } + if (screenHorizontalDelta > 0) { + if (navigationController.currentFocused != null) { + // If current focused node is out of screen, focus out. + var currentNodeRect = navigationController.currentFocused.rect; + if (currentNodeRect.x + currentNodeRect.width <= screenRect.x + screenHorizontalDelta) { + navigationController.focusOut(); + } + } + navigationController.scrollRight(); + } + } + }, + + /* Support function for scrolling left */ + handleDirectionLeft : function() { + if (navigationController.currentFocused != null && + navigationController.isRangeControl(navigationController.currentFocused.element) && + navigationController.rangeNavigationOn) { + navigationController.handleRangeSliderMovement('l'); + } else { //we are not on a range control in navigation mode + var screenRect = navigationController.getUnscaledScreenRect(); + var node = navigationController.findLeftFocusableNode(); + if (node != null) { + var nodeRect = node.rect; + if ((nodeRect.x + nodeRect.width) > (screenRect.x /* - navigationController.SAFE_MARGIN */)) { + navigationController.setRimFocus(node); + return; + } + } + // Only scroll down the screen when there is more content to the left. + var screenHorizontalDelta = screenRect.x; + if (screenHorizontalDelta > navigationController.SAFE_MARGIN) { + screenHorizontalDelta = navigationController.SAFE_MARGIN; + } + if (screenHorizontalDelta > 0) { + if (navigationController.currentFocused != null) { + // If current focused node is out of screen, focus out. + var currentNodeRect = navigationController.currentFocused.rect; + if (currentNodeRect.x > screenRect.x - screenHorizontalDelta + screenRect.width) { + navigationController.focusOut(); + } + } + navigationController.scrollLeft(); + } + } + }, + + /* Highlight the first item on the screen */ + findHighestFocusableNodeInScreen : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + var screenRect = navigationController.getUnscaledScreenRect(); + var firstNode = null; + var firstRect = null; + var length = navigationController.focusableNodes.length; + for ( var i = 0; i < length; i++) { + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + if (navigationController.isRectIntersectingVertically(nodeRect, screenRect)) { + var swap = false; + if (nodeRect.y >= screenRect.y) { + swap = navigationController.needSwapWithDownRect(firstRect, nodeRect); + } + if (swap) { + firstNode = node; + firstRect = nodeRect; + } + } + } + return firstNode; + }, + + /* Find the lowest focusable node visible on the screen */ + findLowestFocusableNodeInScreen : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + + var screenRect = navigationController.getUnscaledScreenRect(); + var firstNode = null; + var firstRect = null; + var length = navigationController.focusableNodes.length; + for ( var i = length - 1; i >= 0; i--) { + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + if (navigationController.isRectIntersectingVertically(nodeRect, screenRect)) { + var swap = false; + // Should select the lowest item in the screen that + // completely fits on screen + if (nodeRect.y + nodeRect.height < screenRect.y + screenRect.height) { + swap = navigationController.needSwapWithUpRect(firstRect, nodeRect); + } + if (swap) { + firstNode = node; + firstRect = nodeRect; + } + } + } + return firstNode; + }, + + /* Find the leftmost focusable node visible on the screen */ + findLeftmostFocusableNodeInScreen : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + + var screenRect = navigationController.getUnscaledScreenRect(); + var firstNode = null; + var firstRect = null; + var length = navigationController.focusableNodes.length; + for ( var i = length - 1; i >= 0; i--) { + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + if (navigationController.isRectIntersectingHorizontally(nodeRect, screenRect)) { + var swap = false; + + if (nodeRect.x < screenRect.x + screenRect.width) { + if (firstNode == null) { + swap = true; + } else { + if (nodeRect.x == firstRect.x) { + if (nodeRect.width > firstRect.width) { + swap = true; + } + } else if (nodeRect.x > firstRect.x) { + swap = true; + } + } + } + if (swap) { + firstNode = node; + firstRect = nodeRect; + } + } + } + return firstNode; + }, + + /* Find the rightmost focusable node visible on the screen */ + findRightmostFocusableNodeInScreen : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + + var screenRect = navigationController.getUnscaledScreenRect(); + var firstNode = null; + var firstRect = null; + var length = navigationController.focusableNodes.length; + for ( var i = 0; i < length; i++) { + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + if (navigationController.isRectIntersectingHorizontally(nodeRect, screenRect)) { + var swap = false; + + if (nodeRect.x >= screenRect.x) { + if (firstNode == null) { + swap = true; + } else { + if (nodeRect.x == firstRect.x) { + if (nodeRect.width < firstRect.width) { + swap = true; + } + } else if (nodeRect.x < firstRect.x) { + swap = true; + } + } + } + if (swap) { + firstNode = node; + firstRect = nodeRect; + } + } + } + return firstNode; + }, + + /* Scrolls downward to the next available focusable item */ + findDownFocusableNode : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + + var index; + + if (navigationController.currentFocused != null) + index = navigationController.indexOf(navigationController.currentFocused); + else + return navigationController.findHighestFocusableNodeInScreen(); + + if (index == -1) { + return navigationController.findHighestFocusableNodeInScreen(); + } + + var currentRect = navigationController.currentFocused.rect; + var screenRect = navigationController.getUnscaledScreenRect(); + var length = navigationController.focusableNodes.length; + var downNode = null; + var downRect = null; + for ( var i = 0; i < length; i++) { + if (i == index) { + continue; + } + + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + + if (navigationController.isRectIntersectingVertically(nodeRect, currentRect)) { + var swap = false; + if (nodeRect.y == currentRect.y) { + if (nodeRect.height == currentRect.height) { + if (i > index) { + return node; + } + } else if (nodeRect.height > currentRect.height) { + swap = navigationController.needSwapWithDownRectInPriority(downRect, nodeRect); + } + } else if (nodeRect.y > currentRect.y) { + swap = navigationController.needSwapWithDownRectInPriority(downRect, nodeRect); + } + if (swap) { + downNode = node; + downRect = nodeRect; + } + } else if (!navigationController.isRectIntersectingHorizontally(nodeRect, currentRect) + && navigationController.isRectIntersectingVertically(nodeRect, screenRect)) { + var swap = false; + if (nodeRect.y > currentRect.y) { + swap = navigationController.needSwapWithDownRect(downRect, nodeRect); + } + if (swap) { + downNode = node; + downRect = nodeRect; + } + } + } + return downNode; + }, + + /* Find the next node that should have focus in the Up direction */ + findUpFocusableNode : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + + var index; + + if (navigationController.currentFocused != null) + index = navigationController.indexOf(navigationController.currentFocused); + else + return navigationController.findLowestFocusableNodeInScreen(); + + if (index == -1) { + return navigationController.findLowestFocusableNodeInScreen(); + } + + var currentRect = navigationController.currentFocused.rect; + var upNode = null; + var upRect = null; + var screenRect = navigationController.getUnscaledScreenRect(); + var length = navigationController.focusableNodes.length; + for ( var i = length - 1; i >= 0; i--) { + if (i == index) { + continue; + } + + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + + if (navigationController.isRectIntersectingVertically(nodeRect, currentRect)) { + var swap = false; + if (nodeRect.y == currentRect.y) { + if (nodeRect.height == currentRect.height) { + if (i < index) { + return node; + } + } else if (nodeRect.height < currentRect.height) { + swap = navigationController.needSwapWithUpRectInPriority(upRect, nodeRect); + } + } else if (nodeRect.y < currentRect.y) { + swap = navigationController.needSwapWithUpRectInPriority(upRect, nodeRect); + } + if (swap) { + upNode = node; + upRect = nodeRect; + } + } else if (!navigationController.isRectIntersectingHorizontally(nodeRect, currentRect) + && navigationController.isRectIntersectingVertically(nodeRect, screenRect)) { + var swap = false; + if (nodeRect.y < currentRect.y) { + swap = navigationController.needSwapWithUpRect(upRect, nodeRect); + } + if (swap) { + upNode = node; + upRect = nodeRect; + } + } + } + return upNode; + }, + + /* Find the next node that should have focus in the Left direction */ + findLeftFocusableNode : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + + var index; + + if (navigationController.currentFocused != null) + index = navigationController.indexOf(navigationController.currentFocused); + else + return navigationController.findLeftmostFocusableNodeInScreen(); + + if (index == -1) { + return navigationController.findLeftmostFocusableNodeInScreen(); + } + + var currentRect = navigationController.currentFocused.rect; + var leftNode = null; + var leftRect = null; + var length = navigationController.focusableNodes.length; + for ( var i = length - 1; i >= 0; i--) { + if (i == index) { + continue; + } + + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + + if (navigationController.isRectIntersectingHorizontally(nodeRect, currentRect)) { + var swap = false; + if (nodeRect.x == currentRect.x) { + if (nodeRect.width == currentRect.width) { + if (i < index) { + return node; + } + } else if (nodeRect.width < currentRect.width) { + if (leftNode == null) { + swap = true; + } else { + if (nodeRect.x == leftRect.x) { + if (nodeRect.width > leftRect.width) { + swap = true; + } + } else if (nodeRect.x > leftRect.x) { + swap = true; + } + } + } + } else if (nodeRect.x < currentRect.x) { + if (leftNode == null) { + swap = true; + } else { + if (nodeRect.x == leftRect.x) { + if (nodeRect.width > leftRect.width) { + swap = true; + } + } else if (nodeRect.x > leftRect.x) { + swap = true; + } + } + } + if (swap) { + leftNode = node; + leftRect = nodeRect; + } + } + } + return leftNode; + }, + + /* Find the next node that should have focus in the Left direction */ + findRightFocusableNode : function() { + if (navigationController.focusableNodes == null || navigationController.focusableNodes.length == 0) + return null; + + var index; + + if (navigationController.currentFocused != null) + index = navigationController.indexOf(navigationController.currentFocused); + else + return navigationController.findRightmostFocusableNodeInScreen(); + + if (index == -1) { + return navigationController.findRightmostFocusableNodeInScreen(); + } + + var currentRect = navigationController.currentFocused.rect; + var rightNode = null; + var rightRect = null; + var length = navigationController.focusableNodes.length; + for ( var i = 0; i < length; i++) { + if (i == index) { + continue; + } + var node = navigationController.focusableNodes[i]; + var nodeRect = node.rect; + + if (nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0) { + continue; + } + + if (navigationController.isRectIntersectingHorizontally(nodeRect, currentRect)) { + var swap = false; + if (nodeRect.x == currentRect.x) { + if (nodeRect.width == currentRect.width) { + if (i > index) { + return node; + } + } else if (nodeRect.width > currentRect.width) { + if (rightNode == null) { + swap = true; + } else { + if (nodeRect.x == rightRect.x) { + if (nodeRect.width < rightRect.width) { + swap = true; + } + } else if (nodeRect.x < rightRect.x) { + swap = true; + } + } + } + } else if (nodeRect.x > currentRect.x) { + if (rightNode == null) { + swap = true; + } else { + if (nodeRect.x == rightRect.x) { + if (nodeRect.width < rightRect.width) { + swap = true; + } + } else if (nodeRect.x < rightRect.x) { + swap = true; + } + } + } + if (swap) { + rightNode = node; + rightRect = nodeRect; + } + } + } + + return rightNode; + }, + + /* + * This function will find all of the focusable items in the DOM and then + * populate the list of elements and their absolute bounding rects + */ + getFocusableElements : function() { + var items = [], + i, j, + iframes = document.getElementsByTagName("iframe"), + iframeFocusables, + focusables = document.body.querySelectorAll(navigationController.querySelector); + + for(i = 0; i < focusables.length; i++) { + items.push(focusables[i]); + } + + for(i = 0; i < iframes.length; i++) { + //Make sure the iframe has loaded content before we add it to the navigation map + if(iframes[i].contentDocument.body !== null) { + iframeFocusables = iframes[i].contentDocument.body.querySelectorAll(navigationController.querySelector); + for(j = 0; j < iframeFocusables.length; j++) { + items.push(iframeFocusables[j]); + } + } + } + + var length = items.length; + // Determine bounding rects and populate list + var boundingRects = []; + for ( var i = 0; i < length; i++) { + var item = items[i]; + var result = navigationController.determineBoundingRect(item); + var bounds = { + 'element' : item, + 'rect' : result.rect, + 'scrollableParent' : result.scrollableParent + }; + /* + * A mouseover event listener is attached to each element so we know + * the currently focused element even if it the mouseover was invoked + * by using touch + */ + bounds.element.addEventListener("mouseover", function(event) { + var length = navigationController.focusableNodes.length; + var element; + for (var i = 0 ; i < length; i++) { + if( this == navigationController.focusableNodes[i].element) { + navigationController.currentFocused = navigationController.focusableNodes[i]; + element = navigationController.currentFocused.element; + if (navigationController.isScrollableElement(element)) { + // this is to workaround the issue where input is selected on the first time + if (element.tagName == 'INPUT') { + element.value = element.value; + } + navigationController.lastCaretPosition = element.selectionStart; + } + } + } + } + ,false); + boundingRects.push(bounds); + } + + return boundingRects; + }, + + /* + * This function will recursively traverse the dom through the element's + * parent nodes to find its true absolute bounding rectangle on the screen + */ + determineBoundingRect : function(element) { + var y = 0; + var x = 0; + var height = element.offsetHeight; + var width = element.offsetWidth; + var scrollableParent = null; + + if (element.offsetParent) { + do { + y += element.offsetTop; + x += element.offsetLeft; + + // See if the parent is scrollable + if (scrollableParent == null && element.parentNode != null + && element.parentNode.style.overflow == 'scroll') { + scrollableParent = element.parentNode; + } + + // If the element is absolute or fixed then it doesn't + // matter what their + // parent's positions are. Their position is already + // accurate + if (element.style.position == 'absolute' || element.style.position == 'fixed') + break; + + if (!element.offsetParent) + break; + } while (element = element.offsetParent) + } + + return { + 'scrollableParent' : scrollableParent, + 'rect' : { + 'y' : y, + 'x' : x, + 'height' : height, + 'width' : width + } + }; + }, + + setRimFocus : function(target) { + try { + // First un focus the old focused item + navigationController.focusOut(); + + // Now set focus to the new item + var mouseover = document.createEvent('MouseEvents'); + mouseover.initMouseEvent('mouseover', true, true, window, 0, target.rect.x, target.rect.y, 1, 1, false, false, + false, false, null, null); + target.element.dispatchEvent(mouseover); + + // Set our focused item + navigationController.currentFocused = target; + + if (navigationController.isAutoFocus(target)) { + target.element.focus(); + } + + // Scroll to the current focus node + navigationController.scrollToRect(navigationController.scaleRect(target.rect)); + } catch(error) { + console.log(error); + console.log(error.message); + } + }, + + focusOut : function() { + if (navigationController.currentFocused != null) { + var priorFocused = navigationController.currentFocused; + navigationController.priorFocusedId = priorFocused.element.getAttribute('id'); + + // Fire our mouse out event + var mouseout = document.createEvent("MouseEvents"); + mouseout.initMouseEvent("mouseout", true, true, window, 0, navigationController.currentFocused.rect.x, + navigationController.currentFocused.rect.y, 1, 1, false, false, false, false, null, null); + navigationController.currentFocused.element.dispatchEvent(mouseout); + navigationController.currentFocused = null; + + if (navigationController.isAutoFocus(priorFocused)) { + priorFocused.element.blur(); + } + } + }, + + /* See if the two rectangles intersect with each other Vertically */ + isRectIntersectingVertically : function(rect1, rect2) { + if (rect1 == null || rect2 == null) + return false; + if (rect2.x <= rect1.x && (rect2.x + rect2.width - 1) >= rect1.x) + return true; + return (rect2.x >= rect1.x && rect2.x <= (rect1.x + rect1.width - 1)); + }, + + /* See if we need to swap the two rects in priority */ + needSwapWithDownRectInPriority : function(downRect, checkedRect) { + if (downRect == null) + return true; + if (checkedRect.y == downRect.y && checkedRect.height <= downRect.height) + return true; + return (checkedRect.y < downRect.y); + }, + + /* Do these rects intersect Horizontally */ + isRectIntersectingHorizontally : function(rect1, rect2) { + if (rect1 == null || rect2 == null) + return false; + if (rect2.y <= rect1.y && (rect2.y + rect2.height - 1) >= rect1.y) + return true; + return (rect2.y >= rect1.y && rect2.y <= (rect1.y + rect1.height - 1)); + }, + + /* Do we need to swap down */ + needSwapWithDownRect : function(downRect, checkedRect) { + if (downRect == null) + return true; + if (checkedRect.y == downRect.y && checkedRect.height < downRect.height) + return true; + return (checkedRect.y < downRect.y); + }, + + /* See if we need to swap the two rects in priority */ + needSwapWithUpRectInPriority : function(upRect, checkedRect) { + if (upRect == null) + return true; + if (checkedRect.y == upRect.y && checkedRect.height >= upRect.height) + return true; + return (checkedRect.y > upRect.y); + }, + + /* Do we need to swap up */ + needSwapWithUpRect : function(upRect, checkedRect) { + if (upRect == null) + return true; + if (checkedRect.y == upRect.y && checkedRect.height > upRect.height) + return true; + return (checkedRect.y > upRect.y); + }, + + /* TODO: Fill this with real code to deal with content scrolls */ + getUnscaledScreenRect : function() { + var screenRect = { + 'y' : navigationController.verticalScroll, + 'x' : navigationController.horizontalScroll, + 'height' : navigationController.height, + 'width' : navigationController.width + }; + return navigationController.unscaleRect(screenRect); + }, + + /* See if this node can be focused */ + isValidFocusableNode : function(node) { + if (node == null) + return false; + + // Should only consider node that is in the valid set of nodes + if (navigationController.indexOf({'element' : node}) == -1) { + return false; + } + + var nodeRect = navigationController.determineBoundingRect(node); + return !(nodeRect == null || nodeRect.width == 0 || nodeRect.height == 0); + }, + + /* See if this node needs a focus */ + isAutoFocus : function(node) { + + if (node.element.tagName == 'INPUT') { + if (node.element.hasAttribute('type')) { + var type = node.element.getAttribute('type').toLowerCase(); + return navigationController.AUTO_FOCUS_INPUT_TYPES.indexOf(type) > 0; + } + } + + if (node.element.tagName == 'TEXTAREA') { + return true; + } + + return false; + }, + + scrollToRect : function(rect) { + // Check vertical scroll. + var verticalScroll = navigationController.verticalScroll; + var newVerticalScroll = verticalScroll; + + // alert("height: " + navigationController.height + " vScroll: " + + // verticalScroll + " rect.y: " + rect.y + " rect.height: " + + // rect.height); + + if (rect.y < verticalScroll) { + newVerticalScroll = Math.max(rect.y, 0); + // alert("rect.y (" + rect.y + ") < vScroll (" + verticalScroll + + // "), need scroll up, newVScroll: " + newVerticalScroll); + } else if (rect.y + rect.height > verticalScroll + navigationController.height) { + /* + * (alert("need scroll down, a: " + (rect.y + rect.height - + * navigationController.height + navigationController.scaleValue( + * navigationController.SAFE_MARGIN ) ) + " b: " + + * (navigationController.virtualHeight - + * navigationController.height) + " c: " + (rect.y + rect.height - + * navigationController.height)); + */ + newVerticalScroll = Math + .min( + rect.y + rect.height - navigationController.height, + navigationController.virtualHeight - navigationController.height); + } + + // Check horizontal scroll. + var horizontalScroll = navigationController.horizontalScroll; + var newHorizontalScroll = horizontalScroll; + if (rect.width >= navigationController.width) { + newHorizontalScroll = Math.max(rect.x, 0); + } else if (rect.x < horizontalScroll) { + newHorizontalScroll = Math.max(rect.x, 0); + } else if (rect.x + rect.width > horizontalScroll + navigationController.width) { + newHorizontalScroll = Math.min(rect.x + rect.width - navigationController.width, + navigationController.virtualWidth - navigationController.width); + } + + if (newHorizontalScroll != horizontalScroll || newVerticalScroll != verticalScroll) { + navigationController.scrollXY(newHorizontalScroll, newVerticalScroll); + } + }, + + scrollDown : function() { + var newVerticalScroll = Math.min(navigationController.verticalScroll + + navigationController.scaleValue(navigationController.SAFE_MARGIN), navigationController.virtualHeight + - navigationController.height); + navigationController.scrollY(newVerticalScroll); + }, + + scrollUp : function() { + var newVerticalScroll = Math.max(navigationController.verticalScroll + - navigationController.scaleValue(navigationController.SAFE_MARGIN), 0); + navigationController.scrollY(newVerticalScroll); + }, + + scrollRight : function() { + var newHorizontalScroll = Math.min(navigationController.horizontalScroll + + navigationController.scaleValue(navigationController.SAFE_MARGIN), navigationController.virtualWidth + - navigationController.width); + navigationController.scrollXY(newHorizontalScroll, navigationController.verticalScroll); + }, + + scrollLeft : function() { + var newHorizontalScroll = Math.max(navigationController.horizontalScroll + - navigationController.scaleValue(navigationController.SAFE_MARGIN), 0); + navigationController.scrollXY(newHorizontalScroll, navigationController.verticalScroll); + }, + + scaleRect : function(rect) { + var newRect = { + 'y' : navigationController.scaleValue(rect.y), + 'x' : navigationController.scaleValue(rect.x), + 'height' : navigationController.scaleValue(rect.height), + 'width' : navigationController.scaleValue(rect.width) + }; + + return newRect; + }, + + scaleValue : function(value) { + return Math.round(value * navigationController.zoomScale); + }, + + unscaleValue : function(value) { + return Math.round(value / navigationController.zoomScale); + }, + + unscaleRect : function(rect) { + var newRect = { + 'y' : navigationController.unscaleValue(rect.y), + 'x' : navigationController.unscaleValue(rect.x), + 'height' : navigationController.unscaleValue(rect.height), + 'width' : navigationController.unscaleValue(rect.width) + }; + + return newRect; + }, + + scrollXY : function(x, y) { + window.scrollTo(navigationController.unscaleValue(x), navigationController.unscaleValue(y)); + }, + + scrollX : function(value) { + window.scrollTo(navigationController.unscaleValue(value), window.pageYOffset); + }, + + scrollY : function(value) { + window.scrollTo(window.pageXOffset, navigationController.unscaleValue(value)); + } + +} + +/* Arms length object so that we can remove any reference to blackberry.* from the navigationController */ + +bbNav = { + init : function() { + if (window.top === window.self) { + var data = { + 'direction' : 3, + 'delta' : 1, + 'zoomScale' : 1, + 'virtualHeight' : screen.height, + 'virtualWidth' : screen.width, + 'verticalScroll' : 0, + 'horizontalScroll' : 0, + 'height' : screen.height, + 'width' : screen.width + }; + + blackberry.focus.onScroll = navigationController.onScroll; + blackberry.focus.onTrackpadDown = navigationController.onTrackpadDown; + blackberry.focus.onTrackpadUp = navigationController.onTrackpadUp; + blackberry.focus.getDirection = navigationController.getDirection; + blackberry.focus.getFocus = navigationController.getFocus; + blackberry.focus.getPriorFocus = navigationController.getPriorFocus; + blackberry.focus.setFocus = navigationController.setFocus; + blackberry.focus.focusOut = navigationController.focusOut; + + navigationController.initialize(data); + + navigationController.handleSelect = blackberry.ui.dialog.selectAsync; + navigationController.handleInputDateTime = blackberry.ui.dialog.dateTimeAsync; + navigationController.handleInputColor = blackberry.ui.dialog.colorPickerAsync; + } + } +} + +addEventListener("load", bbNav.init, false); +}()); \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/StyleSheet.css b/yui-tests/NavModeSmokeTestYUI2.0/StyleSheet.css new file mode 100644 index 0000000..864ae95 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/StyleSheet.css @@ -0,0 +1,35 @@ +button.b1 +{ + position:absolute; + top:300px; + left:140px; + height:50px; +} + +a.a1 +{ + position:absolute; + top:400px; + left:140px; +} + +select.s1 +{ + position:absolute; + top:220px; + left:140px; +} + +textarea.t1 +{ + position:absolute; + top:300px; + left:10px; +} + +input.in1 +{ + position:absolute; + top:300px; + left:270px; +} \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/basic.htm b/yui-tests/NavModeSmokeTestYUI2.0/basic.htm new file mode 100644 index 0000000..0a9326c --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/basic.htm @@ -0,0 +1,290 @@ + + +Nav Mode Smoke Test - Basic + + + + + + + + + + + + + + + + + + + NBA +
+ ASAP +
+
+ Research In Motion
4701 Tahoe Blvd.
Mississauga, ON, + Canada
+
+
+
+
+ + Link + to Google + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/config.xml b/yui-tests/NavModeSmokeTestYUI2.0/config.xml new file mode 100644 index 0000000..acbd518 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/config.xml @@ -0,0 +1,17 @@ + + + + NewScenario_5_Basic_Case + Igor + + Navigation mode - Scenario 5 - Basic Case + + + + + + + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/index.htm b/yui-tests/NavModeSmokeTestYUI2.0/index.htm new file mode 100644 index 0000000..719edd0 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/index.htm @@ -0,0 +1,51 @@ + + + + + Nav Mode Smoke Test + + + + + + + + + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/list.htm b/yui-tests/NavModeSmokeTestYUI2.0/list.htm new file mode 100644 index 0000000..c7e4db6 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/list.htm @@ -0,0 +1,565 @@ + + +Nav Mode Smoke Test - List + + + + + + + + + + + + + + + + + + + +

+ +
+
Coffee
+
- Hot beverage
+
Milk
+
- Cold beverage
+
+
+ +
    +
  1. Coffee
  2. +
  3. Tea
  4. +
  5. Milk
  6. +
+
+ +
    +
  • Coffee
  • +
  • Tea
  • +
  • Milk
  • +
+


+ +

This is heading 1

+

This is heading 2

+

This is heading 3

+

This is heading 4

+
This is heading 5
+
This is heading 6
+
+
+
+
+ + + + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/navmode-browser-direction.js b/yui-tests/NavModeSmokeTestYUI2.0/navmode-browser-direction.js new file mode 100644 index 0000000..464f803 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/navmode-browser-direction.js @@ -0,0 +1,7 @@ +// allow nav mode to be tested outside of BB simulator +if (!blackberry.focus.DOWN) { + blackberry.focus.DOWN = navigationController.DOWN; + blackberry.focus.UP = navigationController.UP; + blackberry.focus.RIGHT = navigationController.RIGHT; + blackberry.focus.LEFT = navigationController.LEFT; +} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/navmode-browser.js b/yui-tests/NavModeSmokeTestYUI2.0/navmode-browser.js new file mode 100644 index 0000000..100e06b --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/navmode-browser.js @@ -0,0 +1,5 @@ +// allow nav mode to be tested outside of BB simulator +if (!this.blackberry) { + this.blackberry = {}; + this.blackberry.focus = {}; +} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/navmode.js b/yui-tests/NavModeSmokeTestYUI2.0/navmode.js new file mode 100644 index 0000000..e938609 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/navmode.js @@ -0,0 +1 @@ +(function(){navigationController={SAFE_MARGIN:30,SUPPRESS_NAVIGATION_INPUT_TYPES:"|checkbox|radio|button|",AUTO_FOCUS_INPUT_TYPES:"|color|date|month|time|week|email|number|password|search|text|url|",REQUIRE_CLICK_INPUT_TYPES:"|file|",querySelector:"textarea:not([x-blackberry-focusable=false]),a:not([x-blackberry-focusable=false]),input:not([x-blackberry-focusable=false]),select:not([x-blackberry-focusable=false]),button:not([x-blackberry-focusable=false]),[x-blackberry-focusable=true]",DOWN:3,UP:2,RIGHT:0,LEFT:1,domDirty:false,currentFocused:null,priorFocusedId:"",lastDirection:null,focusableNodes:[],zoomScale:null,currentDirection:null,delta:null,virtualHeight:null,virtualWidth:null,verticalScroll:null,horizontalScroll:null,height:null,width:null,initialize:function(a){navigationController.assignScrollData(a);navigationController.focusableNodes=navigationController.getFocusableElements();navigationController.SAFE_MARGIN=navigationController.height/10;if(navigationController.device.isBB5()){addEventListener("DOMNodeInsertedIntoDocument",function(){navigationController.domDirty=true},true);addEventListener("DOMNodeRemovedFromDocument",function(){navigationController.domDirty=true},true)}var b=document.body.querySelectorAll("[x-blackberry-initialFocus=true]");if(b.length==0){navigationController.setRimFocus(navigationController.findHighestFocusableNodeInScreen())}else{var c=b[0];if(!navigationController.isValidFocusableNode(c)){c=null}if(c!=null){var d=navigationController.determineBoundingRect(c);var e={element:c,rect:d.rect,scrollableParent:d.scrollableParent};navigationController.setRimFocus(e)}else{navigationController.setRimFocus(navigationController.findHighestFocusableNodeInScreen())}}},device:{isBB5:function(){return navigator.appVersion.indexOf("5.0.0")>=0},isBB6:function(){return navigator.appVersion.indexOf("6.0.0")>=0},isBB7:function(){return navigator.appVersion.indexOf("7.0.0")>=0}},assignScrollData:function(a){navigationController.currentDirection=a.direction;navigationController.delta=a.delta;navigationController.zoomScale=a.zoomScale;navigationController.virtualHeight=a.virtualHeight;navigationController.virtualWidth=a.virtualWidth;navigationController.verticalScroll=a.verticalScroll;navigationController.horizontalScroll=a.horizontalScroll;navigationController.height=a.height;navigationController.width=a.width},getDirection:function(){return navigationController.currentDirection},getFocus:function(){if(navigationController.currentFocused==null)return null;else return navigationController.currentFocused.element.getAttribute("id")},setFocus:function(a){if(a.length==0){navigationController.focusOut();return}var b=null;b=document.getElementById(a);if(b!=null){if(!navigationController.isValidFocusableNode(b)){b=null}}if(b!=null){var c=navigationController.determineBoundingRect(b);var d={element:b,rect:c.rect,scrollableParent:c.scrollableParent};navigationController.setRimFocus(d)}},getPriorFocus:function(){return navigationController.priorFocusedId},onScroll:function(data){navigationController.assignScrollData(data);if(!navigationController.device.isBB5()||navigationController.domDirty){navigationController.focusableNodes=navigationController.getFocusableElements();navigationController.domDirty=false}if(navigationController.currentDirection==navigationController.DOWN){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onDown")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onDown"));return}else{navigationController.handleDirectionDown()}}else if(navigationController.currentDirection==navigationController.UP){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onUp")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onUp"));return}else{navigationController.handleDirectionUp()}}else if(navigationController.currentDirection==navigationController.RIGHT){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onRight")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onRight"));return}else{navigationController.handleDirectionRight()}}else if(navigationController.currentDirection==navigationController.LEFT){if(navigationController.currentFocused&&navigationController.currentFocused.element.hasAttribute("x-blackberry-onLeft")){eval(navigationController.currentFocused.element.getAttribute("x-blackberry-onLeft"));return}else{navigationController.handleDirectionLeft()}}navigationController.lastDirection=navigationController.currentDirection},onTrackpadDown:function(){if(navigationController.currentFocused==null)return;var a=document.createEvent("MouseEvents");a.initMouseEvent("mousedown",true,true,window,0,navigationController.currentFocused.rect.x,navigationController.currentFocused.rect.y,1,1,false,false,false,false,0,null);navigationController.currentFocused.element.dispatchEvent(a)},onTrackpadUp:function(){if(navigationController.currentFocused==null)return;try{var a=document.createEvent("MouseEvents");a.initMouseEvent("mouseup",true,true,window,0,navigationController.currentFocused.rect.x,navigationController.currentFocused.rect.y,1,1,false,false,false,false,0,null);navigationController.currentFocused.element.dispatchEvent(a);var b=document.createEvent("MouseEvents");b.initMouseEvent("click",true,true,window,0,navigationController.currentFocused.rect.x,navigationController.currentFocused.rect.y,1,1,false,false,false,false,0,null);navigationController.currentFocused.element.dispatchEvent(b)}catch(c){}},indexOf:function(a){var b=navigationController.focusableNodes.length;for(var c=0;cnavigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.y+e.height<=a.y+d){navigationController.focusOut()}}navigationController.scrollDown()}},handleDirectionUp:function(){var a=navigationController.getUnscaledScreenRect();var b=navigationController.findUpFocusableNode();if(b!=null){var c=b.rect;if(c.y+c.height>a.y){navigationController.setRimFocus(b);return}}var d=a.y;if(d>navigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.y>a.y-d+a.height){navigationController.focusOut()}}navigationController.scrollUp()}},handleDirectionRight:function(){var a=navigationController.getUnscaledScreenRect();var b=navigationController.findRightFocusableNode();if(b!=null){var c=b.rect;if(c.x<=a.x+a.width){navigationController.setRimFocus(b);return}}var d=navigationController.unscaleValue(navigationController.virtualWidth)-a.x-a.width;if(d>navigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.x+e.width<=a.x+d){navigationController.focusOut()}}navigationController.scrollRight()}},handleDirectionLeft:function(){var a=navigationController.getUnscaledScreenRect();var b=navigationController.findLeftFocusableNode();if(b!=null){var c=b.rect;if(c.x+c.width>a.x){navigationController.setRimFocus(b);return}}var d=a.x;if(d>navigationController.SAFE_MARGIN){d=navigationController.SAFE_MARGIN}if(d>0){if(navigationController.currentFocused!=null){var e=navigationController.currentFocused.rect;if(e.x>a.x-d+a.width){navigationController.focusOut()}}navigationController.scrollLeft()}},findHighestFocusableNodeInScreen:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a=navigationController.getUnscaledScreenRect();var b=null;var c=null;var d=navigationController.focusableNodes.length;for(var e=0;e=a.y){h=navigationController.needSwapWithDownRect(c,g)}if(h){b=f;c=g}}}return b},findLowestFocusableNodeInScreen:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a=navigationController.getUnscaledScreenRect();var b=null;var c=null;var d=navigationController.focusableNodes.length;for(var e=d-1;e>=0;e--){var f=navigationController.focusableNodes[e];var g=f.rect;if(g==null||g.width==0||g.height==0){continue}if(navigationController.isRectIntersectingVertically(g,a)){var h=false;if(g.y+g.height=0;e--){var f=navigationController.focusableNodes[e];var g=f.rect;if(g==null||g.width==0||g.height==0){continue}if(navigationController.isRectIntersectingHorizontally(g,a)){var h=false;if(g.xc.width){h=true}}else if(g.x>c.x){h=true}}}if(h){b=f;c=g}}}return b},findRightmostFocusableNodeInScreen:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a=navigationController.getUnscaledScreenRect();var b=null;var c=null;var d=navigationController.focusableNodes.length;for(var e=0;e=a.x){if(b==null){h=true}else{if(g.x==c.x){if(g.widtha){return h}}else if(i.height>b.height){j=navigationController.needSwapWithDownRectInPriority(f,i)}}else if(i.y>b.y){j=navigationController.needSwapWithDownRectInPriority(f,i)}if(j){e=h;f=i}}else if(!navigationController.isRectIntersectingHorizontally(i,b)&&navigationController.isRectIntersectingVertically(i,c)){var j=false;if(i.y>b.y){j=navigationController.needSwapWithDownRect(f,i)}if(j){e=h;f=i}}}return e},findUpFocusableNode:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a;if(navigationController.currentFocused!=null)a=navigationController.indexOf(navigationController.currentFocused);else return navigationController.findLowestFocusableNodeInScreen();if(a==-1){return navigationController.findLowestFocusableNodeInScreen()}var b=navigationController.currentFocused.rect;var c=null;var d=null;var e=navigationController.getUnscaledScreenRect();var f=navigationController.focusableNodes.length;for(var g=f-1;g>=0;g--){if(g==a){continue}var h=navigationController.focusableNodes[g];var i=h.rect;if(i==null||i.width==0||i.height==0){continue}if(navigationController.isRectIntersectingVertically(i,b)){var j=false;if(i.y==b.y){if(i.height==b.height){if(g=0;f--){if(f==a){continue}var g=navigationController.focusableNodes[f];var h=g.rect;if(h==null||h.width==0||h.height==0){continue}if(navigationController.isRectIntersectingHorizontally(h,b)){var i=false;if(h.x==b.x){if(h.width==b.width){if(fd.width){i=true}}else if(h.x>d.x){i=true}}}}else if(h.xd.width){i=true}}else if(h.x>d.x){i=true}}}if(i){c=g;d=h}}}return c},findRightFocusableNode:function(){if(navigationController.focusableNodes==null||navigationController.focusableNodes.length==0)return null;var a;if(navigationController.currentFocused!=null)a=navigationController.indexOf(navigationController.currentFocused);else return navigationController.findRightmostFocusableNodeInScreen();if(a==-1){return navigationController.findRightmostFocusableNodeInScreen()}var b=navigationController.currentFocused.rect;var c=null;var d=null;var e=navigationController.focusableNodes.length;for(var f=0;fa){return g}}else if(h.width>b.width){if(c==null){i=true}else{if(h.x==d.x){if(h.widthb.x){if(c==null){i=true}else{if(h.x==d.x){if(h.width=a.x)return true;return b.x>=a.x&&b.x<=a.x+a.width-1},needSwapWithDownRectInPriority:function(a,b){if(a==null)return true;if(b.y==a.y&&b.height<=a.height)return true;return b.y=a.y)return true;return b.y>=a.y&&b.y<=a.y+a.height-1},needSwapWithDownRect:function(a,b){if(a==null)return true;if(b.y==a.y&&b.height=a.height)return true;return b.y>a.y},needSwapWithUpRect:function(a,b){if(a==null)return true;if(b.y==a.y&&b.height>a.height)return true;return b.y>a.y},getUnscaledScreenRect:function(){var a={y:navigationController.verticalScroll,x:navigationController.horizontalScroll,height:navigationController.height,width:navigationController.width};return navigationController.unscaleRect(a)},isValidFocusableNode:function(a){if(a==null)return false;if(navigationController.indexOf({element:a})==-1){return false}var b=navigationController.determineBoundingRect(a);return!(b==null||b.width==0||b.height==0)},isAutoFocus:function(a){if(a.element.tagName=="INPUT"){var b=a.element.getAttribute("type").toLowerCase();return navigationController.AUTO_FOCUS_INPUT_TYPES.indexOf(b)>0}return false},scrollToRect:function(a){var b=navigationController.verticalScroll;var c=b;if(a.yb+navigationController.height){c=Math.min(a.y+a.height-navigationController.height,navigationController.virtualHeight-navigationController.height)}if(c-b!=0){navigationController.scrollY(c)}var d=navigationController.horizontalScroll;var e=d;if(a.width>=navigationController.width){e=Math.max(a.x,0)}else if(a.xd+navigationController.width){e=Math.min(a.x+a.width-navigationController.width,navigationController.virtualWidth-navigationController.width)}if(e-d!=0){navigationController.scrollX(e)}},scrollDown:function(){var a=Math.min(navigationController.verticalScroll+navigationController.scaleValue(navigationController.SAFE_MARGIN),navigationController.virtualHeight-navigationController.height);navigationController.scrollY(a)},scrollUp:function(){var a=Math.max(navigationController.verticalScroll-navigationController.scaleValue(navigationController.SAFE_MARGIN),0);navigationController.scrollY(a)},scrollRight:function(){var a=Math.min(navigationController.horizontalScroll+navigationController.scaleValue(navigationController.SAFE_MARGIN),navigationController.virtualWidth-navigationController.width);navigationController.scrollX(a)},scrollLeft:function(){var a=Math.max(navigationController.horizontalScroll-navigationController.scaleValue(navigationController.SAFE_MARGIN),0);navigationController.scrollX(a)},scaleRect:function(a){var b={y:navigationController.scaleValue(a.y),x:navigationController.scaleValue(a.x),height:navigationController.scaleValue(a.height),width:navigationController.scaleValue(a.width)};return b},scaleValue:function(a){return Math.round(a*navigationController.zoomScale)},unscaleValue:function(a){return Math.round(a/navigationController.zoomScale)},unscaleRect:function(a){var b={y:navigationController.unscaleValue(a.y),x:navigationController.unscaleValue(a.x),height:navigationController.unscaleValue(a.height),width:navigationController.unscaleValue(a.width)};return b},scrollX:function(a){window.scrollTo(a,window.pageYOffset)},scrollY:function(a){window.scrollTo(window.pageXOffset,a)}};bbNav={init:function(){var a={direction:3,delta:1,zoomScale:1,virtualHeight:screen.height,virtualWidth:screen.width,verticalScroll:0,horizontalScroll:0,height:screen.height,width:screen.width};blackberry.focus.onScroll=navigationController.onScroll;blackberry.focus.onTrackpadDown=navigationController.onTrackpadDown;blackberry.focus.onTrackpadUp=navigationController.onTrackpadUp;blackberry.focus.getDirection=navigationController.getDirection;blackberry.focus.getFocus=navigationController.getFocus;blackberry.focus.getPriorFocus=navigationController.getPriorFocus;blackberry.focus.setFocus=navigationController.setFocus;blackberry.focus.focusOut=navigationController.focusOut;navigationController.initialize(a)}};addEventListener("DOMContentLoaded",bbNav.init,false)})() \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/readme.txt b/yui-tests/NavModeSmokeTestYUI2.0/readme.txt new file mode 100644 index 0000000..ab47c97 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/readme.txt @@ -0,0 +1,5 @@ +1. The nav mode smoke test can be run directly in desktop browser. +2. These are quick smoke tests to varify the JS navmode logic works as expected, they are by no means comprehensive. +3. YUI 2.9.0 (as oppose to YUI 3) is used so that the Logger Console would show up properly on BB 5.0 + +** Make sure you put replace navmode.js with the one in lib/js folder of the build that you want to test. ** \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/table.htm b/yui-tests/NavModeSmokeTestYUI2.0/table.htm new file mode 100644 index 0000000..e0197f4 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/table.htm @@ -0,0 +1,470 @@ + + +Nav Mode Smoke Test - Table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[table] element is focusable
MonthSavings
January$100
February$80
Sum$180
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
[caption] element is focusable
MonthSavings
January$100
February$80
Sum$180
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
[thead] element is focusable
MonthSavings
January$100
February$80
Sum$180
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
[tbody] element is focusable
MonthSavings
January$100
February$80
Sum$180
+
+ + + + + + + + + + + + + + + + + + + + + + + +
[tfoot] element is focusable
MonthSavings
January$100
February$80
Sum$180
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
[tr] elements are focusable
MonthSavings
January$100
February$80
Sum$180
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
[th] elements are focusable
MonthSavings
January$100
February$80
Sum$180
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
[td] elements are focusable
MonthSavings
January$100
February$80
Sum$180
+
+
+
+
+
+ + + + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/wheel.png b/yui-tests/NavModeSmokeTestYUI2.0/wheel.png new file mode 100644 index 0000000000000000000000000000000000000000..9cab3cfe4fe8c026c070e0d12d5a93b31329cfbd GIT binary patch literal 7756 zcmV-S9<$+zP)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00006 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 zY0CG??|About...

dp.SyntaxHighlighter

Version: {V}

http://www.dreamprojections.com/SyntaxHighlighter

©2004-2005 Alex Gorbatchev. All right reserved.
', + + // tools + ExpandCode : '+ expand code', + ViewPlain : 'view plain', + Print : 'print', + CopyToClipboard : 'copy to clipboard', + About : '?', + + CopiedToClipboard : 'The code is in your clipboard now.' +}; + +dp.SyntaxHighlighter = dp.sh; + +// +// Dialog and toolbar functions +// + +dp.sh.Utils.Expand = function(sender) +{ + var table = sender; + var span = sender; + + // find the span in which the text label and pipe contained so we can hide it + while(span != null && span.tagName != 'SPAN') + span = span.parentNode; + + // find the table + while(table != null && table.tagName != 'TABLE') + table = table.parentNode; + + // remove the 'expand code' button + span.parentNode.removeChild(span); + + table.tBodies[0].className = 'show'; + table.parentNode.style.height = '100%'; // containing div isn't getting updated properly when the TBODY is shown +} + +// opens a new windows and puts the original unformatted source code inside. +dp.sh.Utils.ViewSource = function(sender) +{ + var code = sender.parentNode.originalCode; + var wnd = window.open('', '_blank', 'width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=1'); + + code = code.replace(/' + code + ''); + wnd.document.close(); +} + +// copies the original source code in to the clipboard (IE only) +dp.sh.Utils.ToClipboard = function(sender) +{ + var code = sender.parentNode.originalCode; + + // This works only for IE. There's a way to make it work with Mozilla as well, + // but it requires security settings changed on the client, which isn't by + // default, so 99% of users won't have it working anyways. + if(window.clipboardData) + { + window.clipboardData.setData('text', code); + + alert(dp.sh.Strings.CopiedToClipboard); + } +} + +// creates an invisible iframe, puts the original source code inside and prints it +dp.sh.Utils.PrintSource = function(sender) +{ + var td = sender.parentNode; + var code = td.processedCode; + var iframe = document.createElement('IFRAME'); + var doc = null; + var wnd = + + // this hides the iframe + iframe.style.cssText = 'position:absolute; width:0px; height:0px; left:-5px; top:-5px;'; + + td.appendChild(iframe); + + doc = iframe.contentWindow.document; + code = code.replace(/' + code + ''); + doc.close(); + + iframe.contentWindow.focus(); + iframe.contentWindow.print(); + + td.removeChild(iframe); +} + +dp.sh.Utils.About = function() +{ + var wnd = window.open('', '_blank', 'dialog,width=320,height=150,scrollbars=0'); + var doc = wnd.document; + + var styles = document.getElementsByTagName('style'); + var links = document.getElementsByTagName('link'); + + doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version)); + + // copy over ALL the styles from the parent page + for(var i = 0; i < styles.length; i++) + doc.write(''); + + for(var i = 0; i < links.length; i++) + if(links[i].rel.toLowerCase() == 'stylesheet') + doc.write(''); + + doc.close(); + wnd.focus(); +} + +// +// Match object +// +dp.sh.Match = function(value, index, css) +{ + this.value = value; + this.index = index; + this.length = value.length; + this.css = css; +} + +// +// Highlighter object +// +dp.sh.Highlighter = function() +{ + this.addGutter = true; + this.addControls = true; + this.collapse = false; + this.tabsToSpaces = true; +} + +// static callback for the match sorting +dp.sh.Highlighter.SortCallback = function(m1, m2) +{ + // sort matches by index first + if(m1.index < m2.index) + return -1; + else if(m1.index > m2.index) + return 1; + else + { + // if index is the same, sort by length + if(m1.length < m2.length) + return -1; + else if(m1.length > m2.length) + return 1; + } + return 0; +} + +// gets a list of all matches for a given regular expression +dp.sh.Highlighter.prototype.GetMatches = function(regex, css) +{ + var index = 0; + var match = null; + + while((match = regex.exec(this.code)) != null) + { + this.matches[this.matches.length] = new dp.sh.Match(match[0], match.index, css); + } +} + +dp.sh.Highlighter.prototype.AddBit = function(str, css) +{ + var span = document.createElement('span'); + + str = str.replace(/&/g, '&'); + str = str.replace(/ /g, ' '); + str = str.replace(/'); + + // when adding a piece of code, check to see if it has line breaks in it + // and if it does, wrap individual line breaks with span tags + if(css != null) + { + var regex = new RegExp('
', 'gi'); + + if(regex.test(str)) + { + var lines = str.split(' 
'); + + str = ''; + + for(var i = 0; i < lines.length; i++) + { + span = document.createElement('SPAN'); + span.className = css; + span.innerHTML = lines[i]; + + this.div.appendChild(span); + + // don't add a
for the last line + if(i + 1 < lines.length) + this.div.appendChild(document.createElement('BR')); + } + } + else + { + span.className = css; + span.innerHTML = str; + this.div.appendChild(span); + } + } + else + { + span.innerHTML = str; + this.div.appendChild(span); + } +} + +// checks if one match is inside any other match +dp.sh.Highlighter.prototype.IsInside = function(match) +{ + if(match == null || match.length == 0) + return; + + for(var i = 0; i < this.matches.length; i++) + { + var c = this.matches[i]; + + if(c == null) + continue; + + if((match.index > c.index) && (match.index <= c.index + c.length)) + return true; + } + + return false; +} + +dp.sh.Highlighter.prototype.ProcessRegexList = function() +{ + for(var i = 0; i < this.regexList.length; i++) + this.GetMatches(this.regexList[i].regex, this.regexList[i].css); +} + +dp.sh.Highlighter.prototype.ProcessSmartTabs = function(code) +{ + var lines = code.split('\n'); + var result = ''; + var tabSize = 4; + var tab = '\t'; + + // This function inserts specified amount of spaces in the string + // where a tab is while removing that given tab. + function InsertSpaces(line, pos, count) + { + var left = line.substr(0, pos); + var right = line.substr(pos + 1, line.length); // pos + 1 will get rid of the tab + var spaces = ''; + + for(var i = 0; i < count; i++) + spaces += ' '; + + return left + spaces + right; + } + + // This function process one line for 'smart tabs' + function ProcessLine(line, tabSize) + { + if(line.indexOf(tab) == -1) + return line; + + var pos = 0; + + while((pos = line.indexOf(tab)) != -1) + { + // This is pretty much all there is to the 'smart tabs' logic. + // Based on the position within the line and size of a tab, + // calculate the amount of spaces we need to insert. + var spaces = tabSize - pos % tabSize; + + line = InsertSpaces(line, pos, spaces); + } + + return line; + } + + // Go through all the lines and do the 'smart tabs' magic. + for(var i = 0; i < lines.length; i++) + result += ProcessLine(lines[i], tabSize) + '\n'; + + return result; +} + +dp.sh.Highlighter.prototype.SwitchToTable = function() +{ + // thanks to Lachlan Donald from SitePoint.com for this
tag fix. + var html = this.div.innerHTML.replace(/<(br)\/?>/gi, '\n'); + var lines = html.split('\n'); + var row = null; + var cell = null; + var tBody = null; + var html = ''; + var pipe = ' | '; + + // creates an anchor to a utility + function UtilHref(util, text) + { + return '' + text + ''; + } + + tBody = document.createElement('TBODY'); // can be created and all others go to tBodies collection. + + this.table.appendChild(tBody); + + if(this.addGutter == true) + { + row = tBody.insertRow(-1); + cell = row.insertCell(-1); + cell.className = 'tools-corner'; + } + + if(this.addControls == true) + { + var tHead = document.createElement('THEAD'); // controls will be placed in here + this.table.appendChild(tHead); + + row = tHead.insertRow(-1); + + // add corner if there's a gutter + if(this.addGutter == true) + { + cell = row.insertCell(-1); + cell.className = 'tools-corner'; + } + + cell = row.insertCell(-1); + + // preserve some variables for the controls + cell.originalCode = this.originalCode; + cell.processedCode = this.code; + cell.className = 'tools'; + + if(this.collapse == true) + { + tBody.className = 'hide'; + cell.innerHTML += '' + UtilHref('Expand', dp.sh.Strings.ExpandCode) + '' + pipe + ''; + } + + cell.innerHTML += UtilHref('ViewSource', dp.sh.Strings.ViewPlain) + pipe + UtilHref('PrintSource', dp.sh.Strings.Print); + + // IE has this clipboard object which is easy enough to use + if(window.clipboardData) + cell.innerHTML += pipe + UtilHref('ToClipboard', dp.sh.Strings.CopyToClipboard); + + cell.innerHTML += pipe + UtilHref('About', dp.sh.Strings.About); + } + + for(var i = 0, lineIndex = this.firstLine; i < lines.length - 1; i++, lineIndex++) + { + row = tBody.insertRow(-1); + + if(this.addGutter == true) + { + cell = row.insertCell(-1); + cell.className = 'gutter'; + cell.innerHTML = lineIndex; + } + + cell = row.insertCell(-1); + cell.className = 'line' + (i % 2 + 1); // uses .line1 and .line2 css styles for alternating lines + cell.innerHTML = lines[i]; + } + + this.div.innerHTML = ''; +} + +dp.sh.Highlighter.prototype.Highlight = function(code) +{ + function Trim(str) + { + return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1'); + } + + function Chop(str) + { + return str.replace(/\n*$/, '').replace(/^\n*/, ''); + } + + function Unindent(str) + { + var lines = str.split('\n'); + var indents = new Array(); + var regex = new RegExp('^\\s*', 'g'); + var min = 1000; + + // go through every line and check for common number of indents + for(var i = 0; i < lines.length && min > 0; i++) + { + if(Trim(lines[i]).length == 0) + continue; + + var matches = regex.exec(lines[i]); + + if(matches != null && matches.length > 0) + min = Math.min(matches[0].length, min); + } + + // trim minimum common number of white space from the begining of every line + if(min > 0) + for(var i = 0; i < lines.length; i++) + lines[i] = lines[i].substr(min); + + return lines.join('\n'); + } + + // This function returns a portions of the string from pos1 to pos2 inclusive + function Copy(string, pos1, pos2) + { + return string.substr(pos1, pos2 - pos1); + } + + var pos = 0; + + this.originalCode = code; + this.code = Chop(Unindent(code)); + this.div = document.createElement('DIV'); + this.table = document.createElement('TABLE'); + this.matches = new Array(); + + if(this.CssClass != null) + this.table.className = this.CssClass; + + // replace tabs with spaces + if(this.tabsToSpaces == true) + this.code = this.ProcessSmartTabs(this.code); + + this.table.border = 0; + this.table.cellSpacing = 0; + this.table.cellPadding = 0; + + this.ProcessRegexList(); + + // if no matches found, add entire code as plain text + if(this.matches.length == 0) + { + this.AddBit(this.code, null); + this.SwitchToTable(); + return; + } + + // sort the matches + this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback); + + // The following loop checks to see if any of the matches are inside + // of other matches. This process would get rid of highligting strings + // inside comments, keywords inside strings and so on. + for(var i = 0; i < this.matches.length; i++) + if(this.IsInside(this.matches[i])) + this.matches[i] = null; + + // Finally, go through the final list of matches and pull the all + // together adding everything in between that isn't a match. + for(var i = 0; i < this.matches.length; i++) + { + var match = this.matches[i]; + + if(match == null || match.length == 0) + continue; + + this.AddBit(Copy(this.code, pos, match.index), null); + this.AddBit(match.value, match.css); + + pos = match.index + match.length; + } + + this.AddBit(this.code.substr(pos), null); + + this.SwitchToTable(); +} + +dp.sh.Highlighter.prototype.GetKeywords = function(str) +{ + return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b'; +} + +// highlightes all elements identified by name and gets source code from specified property +dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */) +{ + function FindValue() + { + var a = arguments; + + for(var i = 0; i < a.length; i++) + { + if(a[i] == null) + continue; + + if(typeof(a[i]) == 'string' && a[i] != '') + return a[i] + ''; + + if(typeof(a[i]) == 'object' && a[i].value != '') + return a[i].value + ''; + } + + return null; + } + + function IsOptionSet(value, list) + { + for(var i = 0; i < list.length; i++) + if(list[i] == value) + return true; + + return false; + } + + function GetOptionValue(name, list, defaultValue) + { + var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi'); + var matches = null; + + for(var i = 0; i < list.length; i++) + if((matches = regex.exec(list[i])) != null) + return matches[1]; + + return defaultValue; + } + + var elements = document.getElementsByName(name); + var highlighter = null; + var registered = new Object(); + var propertyName = 'value'; + + // if no code blocks found, leave + if(elements == null) + return; + + // register all brushes + for(var brush in dp.sh.Brushes) + { + var aliases = dp.sh.Brushes[brush].Aliases; + + if(aliases == null) + continue; + + for(var i = 0; i < aliases.length; i++) + registered[aliases[i]] = brush; + } + + for(var i = 0; i < elements.length; i++) + { + var element = elements[i]; + var options = FindValue( + element.attributes['class'], element.className, + element.attributes['language'], element.language + ); + var language = ''; + + if(options == null) + continue; + + options = options.split(':'); + + language = options[0].toLowerCase(); + + if(registered[language] == null) + continue; + + // instantiate a brush + highlighter = new dp.sh.Brushes[registered[language]](); + + // hide the original element + element.style.display = 'none'; + + highlighter.addGutter = (showGutter == null) ? !IsOptionSet('nogutter', options) : showGutter; + highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls; + highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll; + + // first line idea comes from Andrew Collington, thanks! + highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine; + + highlighter.Highlight(element[propertyName]); + + // place the result table inside a div + var div = document.createElement('DIV'); + + div.className = 'dp-highlighter'; + div.appendChild(highlighter.table); + + element.parentNode.insertBefore(div, element); + } +} + + +dp.sh.Brushes.Xml = function() +{ + this.CssClass = 'dp-xml'; +} + +dp.sh.Brushes.Xml.prototype = new dp.sh.Highlighter(); +dp.sh.Brushes.Xml.Aliases = ['xml', 'xhtml', 'xslt', 'html', 'xhtml']; + +dp.sh.Brushes.Xml.prototype.ProcessRegexList = function() +{ + function push(array, value) + { + array[array.length] = value; + } + + /* If only there was a way to get index of a group within a match, the whole XML + could be matched with the expression looking something like that: + + () + | () + | (<)*(\w+)*\s*(\w+)\s*=\s*(".*?"|'.*?'|\w+)(/*>)* + | () + */ + var index = 0; + var match = null; + var regex = null; + + // Match CDATA in the following format + // <\!\[[\w\s]*?\[(.|\s)*?\]\]> + this.GetMatches(new RegExp('<\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\]>', 'gm'), 'cdata'); + + // Match comments + // + this.GetMatches(new RegExp('', 'gm'), 'comments'); + + // Match attributes and their values + // (\w+)\s*=\s*(".*?"|\'.*?\'|\w+)* + regex = new RegExp('([\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\'|\\w+)*', 'gm'); + while((match = regex.exec(this.code)) != null) + { + push(this.matches, new dp.sh.Match(match[1], match.index, 'attribute')); + + // if xml is invalid and attribute has no property value, ignore it + if(match[2] != undefined) + { + push(this.matches, new dp.sh.Match(match[2], match.index + match[0].indexOf(match[2]), 'attribute-value')); + } + } + + // Match opening and closing tag brackets + // + this.GetMatches(new RegExp('', 'gm'), 'tag'); + + // Match tag names + // 2DMT7{-^frOVv~QkPP&Ewq->nsP|D1x-16aL6T+fS1y->At;?rCzDB|UT?Kn!l4k)^P(uaoX&VWPDLVS z3^V9-9LI%%!9*fqvszIE(P_0zD&=vzEoQSQ2rh>sl}cr^+0oI_$ml469m^7AOPfd(=_d{J75s9+iVaBkbZwW7K_qR%xHAj zZA^+0cp;Nc8x49<6f&7K%Vrbt1j8^{Hj8K=L<8$}Xgn5AC6gKeKwua}V6zDW0ky+n zPoiu?Rem84SSyDdxl|Me9*rCY$wnJQ@)2dcAg=HN`NnMuR|* zD2N=->(D$dS0plOHDk$SLWdv_09wr!r`?{fnB8U%1p_?KN&d%Fyp;aus(YhvenKL9 zEqOgl(J`p%+jYPBy@S-_&Etzpk|12+#`W#@(A zhTf0QpWXgq#MHZ=n9i*1S=FSyQZ&77VCc`5O}C1cxkIuU-T0K!2kk|dPt*-6I)~0* zlB4$nhWdWPi^}cyCsppkmsLccPjtVtW8L+i`<&LMi^Y*uYp2V*&V6w(iB9iyet-Ji zE^gtL*CQ=opLw|!>3FcY`%3@H8CC0#Ty`w{r0UeSCC481Kat;Ruc|?1ibbS9pwe&aT#R+%DO!J$i(uMa1rzv{|hT2OWx6~*_%5`JYm*@H#8hc!=^BT9m z+%&J7E#ACn?_jQQp?`4SYGp~Ms(0dE;PK_cq|z;$f2jHTPb(&=Mx1xf)WWVGo*X$> z*l@N>?i$%zR=R4|rAGz6xmzUTqzg_;#`$Eox|(stz^sBx^0xAdCkjR}PF8-fVWfY? z#2S~h^p|R&Tn)6wYt_;jHNEOO?9t)N6)U8{56g}{Rdu}G+fh+CC3FX^oA8yYynezC z+3NZgJ9al*D`EHc1PT{3@-?QnZqD&cuDSQBz+7{08!`Ee%vn@c&|TRww})9IX)1XB z>b&Gvnd;oK35u~c7pf?C7VjDBl2q-PvbcZT9;piP-Q0a-@m%tS+}ZfYi)XEp6Oyq) gN%dXecuDQ}@=FVLc0apP+!WuqblxeMyjZg0UuMopT>t<8 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/syntax.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/syntax.js new file mode 100644 index 0000000..4db3440 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/syntax.js @@ -0,0 +1,134 @@ +(function() { + var Dom = YAHOO.util.Dom, + Event = YAHOO.util.Event, + items = null, + openWindow = function(node, print) { + var n = Dom.get(node.id + '-plain'), + code = n.value, win = null, + h = n.offsetHeight; + + code = code.replace(//g, '>'); + win = window.open('', "codeview", "status=0,scrollbars=1,width=600,height=400,menubar=0,toolbar=0,directories=0"); + win.document.body.innerHTML = '
' + code + '
'; + + if (print) { + YAHOO.lang.later(1000, win, function() { + win.focus(); + win.print(); + win.focus(); + }); + } + }, + handleClick = function(e) { + var tar = Event.getTarget(e); + if (tar.tagName.toLowerCase() == 'a') { + var type = tar.innerHTML.replace(/ /g, ''); + switch (type) { + case 'print': + openWindow(tar.parentNode.parentNode, true); + break; + case 'viewplain': + openWindow(tar.parentNode.parentNode); + break; + case 'togglelinenumbers': + if (Dom.hasClass(tar.parentNode.parentNode, 'yui-syntax-highlight-linenumbers')) { + Dom.removeClass(tar.parentNode.parentNode, 'yui-syntax-highlight-linenumbers') + } else { + Dom.addClass(tar.parentNode.parentNode, 'yui-syntax-highlight-linenumbers') + } + break; + case 'copy': + break; + } + } + Event.stopEvent(e); + }, + init = function() { + items = Dom.getElementsByClassName('yui-syntax-highlight'); + for (var i = 0; i < items.length; i++) { + var header = document.createElement('div'); + header.className = 'syn-header hidden'; + header.innerHTML = 'view plain | print | toggle line numbers'; + Event.on(header, 'click', handleClick); + items[i].insertBefore(header, items[i].firstChild); + Event.on(items[i], 'mouseenter', function(e) { + var tar = Dom.getElementsByClassName('syn-header', 'div', Event.getTarget(e)); + Dom.removeClass(tar, 'hidden'); + }); + Event.on(items[i], 'mouseleave', function(e) { + var tar = Dom.getElementsByClassName('syn-header', 'div', Event.getTarget(e)); + Dom.addClass(tar, 'hidden'); + }); + } + }; + + + var loader = new YAHOO.util.YUILoader({ + require: ["event-mouseenter"], + base: '../../../2.x/build/', + onSuccess: init, + timeout: 10000 + }); + loader.insert(); + + +})(); + +/* +if (YUI) { + YUI(yuiConfig).use('node', 'event-mouseenter', 'later', function(Y) { + var items = Y.all('.yui-syntax-highlight'), + openWindow = function(node, print) { + var n = Y.get('#' + node.get('id') + '-plain'), + code = n.get('value'), win = null, + h = n.get('offsetHeight'); + + code = code.replace(//g, '>'); + win = window.open('', "codeview", "status=0,scrollbars=1,width=600,height=400,menubar=0,toolbar=0,directories=0"); + win.document.body.innerHTML = '
' + code + '
'; + + if (print) { + Y.later(1000, win, function() { + win.focus(); + win.print(); + win.focus(); + }); + } + }, + handleClick = function(e) { + if (e.target.get('tagName').toLowerCase() == 'a') { + var type = e.target.get('innerHTML').replace(/ /g, ''); + switch (type) { + case 'print': + openWindow(e.target.get('parentNode.parentNode'), true); + break; + case 'viewplain': + openWindow(e.target.get('parentNode.parentNode')); + break; + case 'togglelinenumbers': + e.target.get('parentNode.parentNode').toggleClass('yui-syntax-highlight-linenumbers'); + break; + case 'copy': + break; + } + } + e.halt(); + }; + + + + items.each(function(i) { + //var header = Y.Node.create(''); + var header = Y.Node.create(''); + header.on('click', handleClick); + i.insertBefore(header, i.get('firstChild')); + i.on('mouseenter', function() { + header.removeClass('hidden'); + }); + i.on('mouseleave', function() { + header.addClass('hidden'); + }); + }); + }); +} +*/ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui-candy.jpg b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui-candy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6c61b9522df7f1501a4d35af9b00f14e0f5c0cd0 GIT binary patch literal 11389 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

o4*iCTX#cpkB*1T=RwTZA*)0#g41(`Q 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 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.css new file mode 100644 index 0000000..20c5497 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.css @@ -0,0 +1,416 @@ +/* +Copyright (c) 2007, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.4.0 +*/ +html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;font-variant:normal;}sup {vertical-align:text-top;}sub {vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}legend{color:#000;} + +body {font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;} + +body{text-align:center;}#ft{clear:both;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.301em;min-width:750px;}#doc2{width:73.074em;*width:71.313em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.117em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.3207em;*width:12.0106em;}.yui-t1 #yui-main .yui-b{margin-left:13.3207em;*margin-left:13.0106em;}.yui-t2 .yui-b{float:left;width:13.8456em;*width:13.512em;}.yui-t2 #yui-main .yui-b{margin-left:14.8456em;*margin-left:14.512em;}.yui-t3 .yui-b{float:left;width:23.0759em;*width:22.52em;}.yui-t3 #yui-main .yui-b{margin-left:24.0759em;*margin-left:23.52em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.512em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.512em;}.yui-t5 .yui-b{float:right;width:18.4608em;*width:18.016em;}.yui-t5 #yui-main .yui-b{margin-right:19.4608em;*margin-right:19.016em;}.yui-t6 .yui-b{float:right;width:23.0759em;*width:22.52em;}.yui-t6 #yui-main .yui-b{margin-right:24.0759em;*margin-right:23.52em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gb .yui-u,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;margin-left:2%;width:32%;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:.8%;}.yui-gb .yui-u{float:right;}.yui-gb div.first{margin-left:0;float:left;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-g div.first,.yui-gc div.first,.yui-gc div.first div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first{float:left;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g div.first{*margin:0;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-gc div.first,.yui-gc div.first,.yui-gd .yui-g,.yui-gd .yui-u{width:66%;}.yui-gd div.first,.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf div.first{width:24%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first {float:left;}.yui-ge div.first,.yui-gf .yui-g,.yui-gf .yui-u{width:74.2%;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}.yui-gb .yui-u{float:left;} + +blockquote,ul,ol,dl { + margin:1em; +} +ol,ul,dl { + margin-left:2em; +} +ol li { + list-style: decimal outside; +} +ul li { + list-style: disc outside; +} + +/*begin YDN/YUI styles*/ +#bd {padding-top:1em;} +.yui-gb:after{clear:none;} +#doc3 {min-width:950px;} +h1, h2, h3, h4, h5, h6 {font-weight:bold; color:#E76300;} +h1, h2, h3, h4, h5, h6, p {line-height:1.2em; font-size:100%; margin:1em 0 0 0;} +h1.first-content, h2.first-content, h3.first-content {margin-top:0; padding-top:0; border:none;} /*if an h is the first thing on the page or in a section, it should be flush with the top border of its content area; otherwise, its content area should be padded to create space.*/ +p { margin-bottom:1em } +h1 { font-size: 136%; padding:0; padding-top:18px} +.wiki h1 { font-size: 120%; padding:0; margin-bottom:1em} +h2 { font-size: 110%; margin-top:1.5em; margin-bottom:.2em; padding:1em 0 0 0; border-top:1px dashed #C3D2DC;} +h2.first { border-top:none; margin-top:0; margin-bottom:.2em;} +#doc3 h2.first { float:none; /*float specified to resolve conflict on generic float declaration for .first in grids*/} +h4 {margin-top:1em; color: #000;} +ul, ol, dl, dd {margin-left:30px;} +dt { font-weight:bold; } +ul, ol {margin-bottom:.7em;} +ul {list-style:disc;} +ol {list-style:decimal;} +strong {font-weight:bold;} +em {font-style:italic;} + +a, a code {color:#0000de;} +a:visited, a:visited code {color:#639;} +a:active, a:active code {color: #f00;} + +h1 a { color:#E76300; } +h1 a:visited {color:#E76300} + +#logo_pane { display: none; } + +#ygma { margin:.5em auto 1em auto; } + +#bd ol {} +#bd ol li p { margin-left:0} +#bd ol li ol {list-style:lower-alpha} +#bd ol li ol li {margin-bottom:1em} +#bd ol li ol li ol{list-style:lower-roman} +#bd ol li ol li ol li {margin-bottom:1em} + +#bd p.errormessage {background:url(http://l.yimg.com/a/i/us/search/gr/alertbubble.gif) 0 0 no-repeat; padding-left:30px; margin:2em 2em 2em 1em; font-weight:bold} + +/*formerly #bd targeting*/ +ul {margin-top:2px; } +ul.topspace { margin-top:1em } +ul li { margin:0 17px 0 7px; } +ul li ul { margin-top:0em } +ul.plain {margin-top: 0; list-style: none;} +ul.plain ul {margin-top: 0; list-style: none;} +ul.jump {list-style: none; margin-top: 1em;} +ul.jump li {margin-top: .5em;} + +/*#bd table { margin:10px 17px; width:720px; }*/ +/*#bd th { background:#B6CDE1; padding:2px; color:#fff; vertical-align:top} +#bd td { padding:2px; vertical-align:top} +#bd td.even { background:red; }*/ + +h2.classname { border-top:none; margin-top:0; margin-bottom:.2em; font-size: 130%; color:#000000} +h3.breadcrumb { border-top:none; margin-top:0; margin-bottom:.2em; font-size: 80%; color:#000000} +h3.methods { border-top:none; margin-top:0; margin-bottom:.2em; font-size: 100%; color:#000000} + +.screenshot {border:thin solid #999999; margin:8px;} + +#toc {background-color:#ecf5fa; padding:0; border:1px solid #89d } +#toc ul {margin:0; padding:0;} +#toc ul li {list-style:none; padding:0; margin:0; font-size:85%; } +#toc ul li.selected { font-weight:bold; color:#fff; background:#f82; padding:0; } +#toc ul li.selected a { color:#fff; } +#toc ul li a { display:block; padding:2px 2px 2px 10px; text-decoration:none; } +#toc ul li a:hover { color:#fff; background:#e60; } +#toc ul li em { display:none; } +#toc ul li.sect { font-weight:bold; color:#fff; background:#89d; padding:2px 0; text-indent:2px; margin-top:2px;} +#toc ul li.first {margin-top:0;} + +#ft { margin-top:4em } +#ft p { padding-bottom:2em; margin:0; text-align:center; font-size:80%; line-height:1.4em} +#ft p.first { padding:1em 0 0 0; margin:0; } + +#pagetitle {background: url(http://l.yimg.com/a/i/ydn/bg_hd.gif) 0 0 repeat-x #B6CDE1; border: 1px solid #93B2CC; } +#pagetitle h1 {text-indent:15px; padding:4px 0 2px 0; margin:0; color:#000; font-size:120%; font-weight:bold; position:relative; left:-1px; top:-1px; margin-right:-2px;} +#pagetitle h1 em {color:#FF9933; font-size:60%; font-weight:bold; font-style:normal; position:relative; top:-6px} + +#ygunav {background:#eee; border-bottom:2px solid #ccc; padding:0 10px;font-size:78%;text-align:right;margin-bottom:6px;height:2.5em;line-height:2.5em;} +html>body #ygunav {overflow:hidden;} +#ygunav strong {font-family:verdana;} +#ygunav p {display:inline;margin:0;padding:0;} +#ygunav p em {float:left;text-align:left;font-style:normal; padding-top:.7em} +* html #ygunav p em {margin-top:1px;} +#ygunav p em i {visibility:hidden;} +#ygunav a {color:#000;} +#ygunav form {display:inline;margin:0 0 0 1em;} +#ygsp {width:8em;font-size:110%;padding:0;vertical-align:middle;} +#ygunav .ygbt {background:#dcdcdc;font:110% verdana;position:relative;top:1px;} +* html #ygunav .ygbt {top:4px;} +* html>body #ygunav .ygbt {line-height:0;top:-4px;} +#ygunav label {color:#666;font-family:tahoma;top:1px;} + +#bd ol.getstarted { margin:0; padding:0; } +#bd ol.getstarted li { font-weight:bold; color:#668AA8; margin-bottom:1em; padding-left:20px; list-style-type:none;} +#bd ol.getstarted li p { color:#000; font-weight:normal; margin:0 0 0 20px; padding:0 } + +/* removing +#bd p {margin-bottom:8px;} +*/ + +#promo {zoom:1;border: 1px solid #B6CDE1; padding:1em; /*position:relative;*/ background-color:#FFF5DF;} +/*#promo ul {margin-bottom:0;}*/ +#promo h1 {margin-top:0; padding-top:0} +#promo h2 {line-height:1.2em; color:#668AA8; margin-top:0; padding-top:0; border:none; font-size:100%} +#promo p {line-height:1.2em; font-weight:400;} +#promo h1 em {float:right; top:0; right:0; font-style:normal; font-size:80%} +#promo h4 { color:#E76300; } +#promo.component div {width:48%; float:left;} +#promo:after {content:'.';visibility:hidden;clear:left;height:0;display:block;} +#promo p#api {margin-top:.2em;} +#promo #download img {float:left; padding:0 0.5em 0.5em 0;} +#promo #blog {clear:left;} + + +code {font-family:"Courier New"; font-size: 100%; font-weight:bolder;} + +div.apisummary {height:auto; margin:10px 0; width:auto; zoom:1;} +div.apisummary table {font-size:inherit;font:100%; border-collapse:separate; border:1px solid #666666; border-left:none;} +#doc3 div.apisummary table td, #doc3 div.apisummary table th {padding:.35em; vertical-align:top;} +div.apisummary table th { background:#B6CDE1; color:#fff; vertical-align:top; font-weight:bold;} +div.apisummary table td { border-top:1px solid #666666;} +div.apisummary table td, div.apisummary table th { border-left:1px solid #666666;} +div.apisummary table tr { background-color:#ddd;} +div.apisummary table tr.odd { background-color:#fff; } +div.apisummary table tfoot tr { background-color:#fff; } + +dl#menuwidgets dt {font-weight:bold;} +dl#menuwidgets {margin:0 0 0 1.5em;} +img.example {clear:right;margin-bottom:10px;margin-left:10px;border:0;float:right;border:1px solid #999;} + +/*YUI theater box on main page top right corner*/ +#yui-theater {width:316px; overflow:hidden;} +#yui-theater h3 {margin:0; padding:0; color:#E76300; font-size:100%; font-weight:bold; font-stretch:expanded;} +#yui-theater h2 {margin:0 0 10px 0; padding:0; border:none; color:#000; font-size:122%; font-weight:bold;} +#yui-theater p {margin:7px 0 0 0;} +#yui-theater div {float:right; font-size:85%;} + +/*rss reader styles*/ +p.loading-content {background-image:url(http://l.yimg.com/a/i/ydn/yuiweb/img/busy_arrow.gif); background-position:top left; background-repeat:no-repeat; height:20px;padding:4px 0 0 25px; margin:0;} +#doc3 ul.yuirssreader {margin:0; padding:0;} +#doc3 ul.yuirssreader li {list-style-type:none;padding:5px 0 0 12px; margin:0;} +#doc3 ul.yuirssreader li p {margin:0; padding:0;} +ul.yuirssreader cite {color:#666666; margin:0;} +span.yuirssreader-date {font-size:77%; color:#E76300;} +img.rssbadge {display:inline;border:none !important;} + +#index-secondary {width:316px;float:right;margin-left:10px;} +#index-main {margin-right:331px;} +#index-main #promo li {list-style-type:none;font-size:92%;margin-top:2px;} +#index-main #promo ul {margin:0;} + +/*styles for right gutter on component pages*/ +#cheatsheet h3 {margin-top:0;} +#cheatsheet img, #componentvideo img {margin:.5em 0 .2em 0; border:1px solid #999;} +#cheatsheet p {margin:0; font-size:77%;} +#cheatsheet h4, .example-container h4, #examples h4 {margin:0.2em 0 .1em 0; color:#668AA8; font-size:92%;} +#examples ul, #morereading ul, #module ul {font-size:85%; list-style:circle; margin:0 0 1em 10px;} +#examples p, #componentvideo p {font-size:85%; margin:0 0 .2em 0;} +#examples li.selected {font-weight:bold;} + +/*styles for example pages*/ +.example .promo {background-color:#89d;border-color:#666666; padding:1em;} +.example .promo h1, .example .promo h2, .example .promo h3 {color:#FFCC66;} +.example .promo h1 {font-size:159%; padding-top:0; margin-top:0;} +.exampleIntro, .exampleIntro p, .exampleIntro a, .exampleIntro a code {color:#fff;} +.example .promo p {margin-top:.7em;} + +.example cite.byline {display:block; padding:0.5em; background-color:#eee; border:1px solid #000;margin-bottom:5px} + +firstContent {margin-top:0; padding-top:0;} +#logger {margin-top:1em;} +.example-container {background-color:#F1F6F7;} + +.example-container .bd {padding:1em; position:relative; z-index:1; zoom:1;} +.example-container .bd .bd {padding:0; position:static;} /* Reset to defaults to ensure styles are only applied to the top-level .bd of .example-container */ +.example-container>.bd:after {content:'.';visibility:hidden;clear:left;height:0;display:block;} +.example-container .exampleHd {background: url(example-hd-bg.gif) 0 0 repeat-x #4E4D4C; } +.example-container h3 {margin:.2em 0 .4em 0;} +.example .example-container h1, .example .example-container h2, .example .example-container h3, .example .example-container h4, .example .example-container h5, .example .example-container h6 {color:#E76300; font-weight:bold;} +.example-container a {color:#000;} +.example-container a:visited, .example-container a:visited code {color:#000;} +.example-container a:active, .example-container a:active code {color: #000;} + +#loggerGloss {margin-top:.5em; font-size:85%;} +#loggerDiv {font-size:77%;text-align:left;margin-top:.5em; visibility:hidden; height:280px; } /*gets turned on by script when loaded */ +#loggerDiv.yui-log {padding:.4em;width:96%;background-color:#FBE7D9;border:1px solid #666;font-family:monospace;z-index:9000;} +#loggerDiv.yui-log p {margin:1px;padding:.1em;} +#loggerDiv.yui-log .yui-log-hd {margin:0; padding:0; background-color:#CECCCC;} +#loggerDiv.yui-log .yui-log-hd h4 {display:none;} +#loggerDiv.yui-log .yui-log-bd {width:100%;height:20em;background-color:#FFF;border:1px solid #ECECEC;overflow-y:auto;overflow-x:hidden;} +#loggerDiv.yui-log .yui-log-bd pre {border-top:1px solid #ECECEC;} +#loggerDiv.yui-log .yui-log-bd code p {margin:1px 0;} +#loggerDiv.yui-log .yui-log-ft .yui-log-categoryfilters {margin-top:.5em;clear:right;} +#loggerDiv.yui-log .yui-log-ft .yui-log-sourcefilters {margin-top:.5em;border:none; clear:both;} +#loggerDiv.yui-log .yui-log-btns {margin-top:.2em;padding:.2em;background: url(bg_hd.gif) 0 0 repeat-x #CECCCC; text-align:right; float:none; position:static;} +#loggerDiv.yui-log .yui-log-filtergrp {margin-right:.3em; float:left; display:block} +#loggerDiv.yui-log .yui-log-ft {margin-top:.3em;margin-bottom:.3em; font-family:verdana; zoom:1;} +/*bug in Safari when this is applied to .yui-log-ft:*/ +#loggerDiv.yui-log:after {content:'.';visibility:hidden;clear:both;height:0;display:block;} +.example-container.newWindow {text-align:center;} +p.newWindowButton {text-align:right; margin-top:0; padding:.5em;} +.bd p.newWindowButton {text-align:center;} /*when new window is required and button appears in middle of example body*/ +p.loggerButton {text-align:center;} +#loggerLink a, #newWindowLink a {font-size:115%; font-weight:bold; color:#000099;} +#newWindowLink a {font-size:107%;} +#loggerModule {padding-bottom:.2em;} + +/*right column navigation on example rosters*/ +#exampleToc {background-color:#ecf5fa; padding:0; border:1px solid #89d; margin-top:.5em;} +#exampleToc ul {margin:0; padding:0; font-size:85%; } +#exampleToc ul li {list-style:none; padding:0; margin:0; } +#exampleToc ul li.selected { font-weight:bold; color:#fff; background:#000099; padding:0; } +#exampleToc ul li.selected a { color:#fff; } +#exampleToc ul li a { display:block; padding:2px 2px 2px 10px; text-decoration:none; } +#exampleToc ul li a:hover { color:#fff; background:#e60; } +#exampleToc ul li.selected a code { color:#fff; } + +/*theater page styles*/ +.theater h1 {border-bottom:1px dashed #CCC; margin-bottom:1em;padding-bottom:.2em;} +.theater img {border:1px solid #666;} +.theater img.last {border:1px solid #666;} +.theater p.details {font-size:77%; color:#666; margin:.2em 0 0 0; padding:0;} +.theater p.description, #doc3 .theater ul li {font-size:85%; margin:0; padding:0; color:#333;} + +#readmePanel .hd { font-weight:bold; font-size:129%; color:#fff; background:#89d; } +#readmePanel .bd {text-align:left; overflow:auto;} +#readmePanel .ft {text-align:right; background-color:#E7E7E7; font-size:85%;} +/* Browser specific (not valid) styles to make preformatted text wrap */ +#readmePanel .bd pre { + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + font-size: 100%; + color:#000033;} + +/*ed eliot's server-side delicious badge css*/ + #delicious-badge {margin-top:.6em; font: 85% Arial, sans-serif; border: 1px solid #b1b1b1; } +#delicious-badge .bookmark { background: url(http://images.del.icio.us/static/img/delicious.small.gif) no-repeat left center; padding-left: 15px; font-weight: bold; } +#delicious-badge p, #delicious-badge div { padding: 7px; margin: 0; text-align: center; } +#delicious-badge a { color: #00f; text-decoration: none; } +#delicious-badge div { background: #eee; } +#delicious-badge div span { font-weight: bold; color: #000; } +#delicious-badge ul, #delicious-badge li { display: inline; list-style: none; padding: 0; margin: 0; } +#delicious-badge li { margin-left: 5px; } +#delicious-badge li span { position: absolute; left: -999px; width: 999px; } +#delicious-badge .saved-by { color: #999; } +#delicious-badge .saved-by span { background: #00f; padding: 3px; color: #fff; } +#delicious-badge .be-first { font-size: 85%; color: #999; } +#delicious-badge .tag-size-1 { font-size: 100%; } +#delicious-badge .tag-size-2 { font-size: 107%; } +#delicious-badge .tag-size-3 { font-size: 114%; } +#delicious-badge .tag-size-4 { font-size: 122%; } +#delicious-badge .tag-size-5 { font-size: 129%; } + +/*faq page:*/ +.yui-ge .yui-g {width:98%;} +.yui-ge .yui-g .yui-u {width:48.1%;} +#questions {margin:1em 0 2em 0; padding:0.5em; border:1px solid #838383; background-color:#E6E6E6;} +#questions ul {margin:0; list-style:none;} +#yui-main #questions li {padding-bottom:.2em; font-size:85%; margin:0;} +#questions li a {display:block; padding:.6em; text-decoration:none;} +#questions li a:hover {background-color:#F6F6F6;} + +/*for notes on file includes*/ +#configuratorBadge {display:block; float:left; margin:0 .5em .5em 0;} +.include-notice {clear:left; border:1px solid #6F7EA1; background:#eee; font:77% verdana; padding:.7em;} +.include-notice p.firstP {margin-top:0;} +.include-notice p.lastP {margin-bottom:0;} +.include-notice strong {color:#990000;} +.configurator-notice p {font-size:85%;} + +/*for site search suggest via autocomplete*/ +#ygunav {overflow:visible !important;} +#sitesearch {float:right; width:40em; position:relative; text-align:right;} +#searchinput {width:15em; font-size:11px; font-weight:bold; position:relative; top:2px;} + +/*RSS links*/ +#yuiblogTitle a, #ydnJsTitle a, #delicious a, #yui-theater h3 a { color: #E76300; text-decoration: none; } +#yuiblogTitle a:hover, #ydnJsTitle a:hover, #delicious a:hover, #yui-theater h3 a:hover { text-decoration: underline; } + + +/* New syntax Highlighter Core */ +.yui-syntax-highlight { + background-color: #F5F5F5; + border: 1px solid #D9D9D9; + padding: .75em; + overflow-x: auto; + position: relative; + margin-bottom: 15px; + _width: 97%; + _margin-bottom: 1.5em; +} + +.yui-syntax-highlight .numbers { + display: none; +} + +.yui-syntax-highlight-linenumbers .numbers { + display: block; +} + +.yui-syntax-highlight-linenumbers .nonumbers { + display: none; +} + +.yui-syntax-highlight ol { + margin-top: 0; + margin-left: 2em; +} + +.yui-syntax-highlight ol li { + margin-bottom: 0; +} + +.yui-syntax-highlight textarea { + display: none; +} + +.yui-syntax-highlight .syn-header { + position: absolute; + right: 5px; + top: 0; +} +.yui-syntax-highlight .hidden { + visibility: hidden; + position: absolute; + top: 0; + left: 0; + height: 0px; + width: 0px; +} + +/* HTML Colors */ +.yui-syntax-highlight .html4strict {font-family:monospace;} +.yui-syntax-highlight .html4strict .imp {font-weight: bold; color: red;} +.yui-syntax-highlight .html4strict .kw2 {color: #000000; font-weight: bold;} +.yui-syntax-highlight .html4strict .kw3 {color: #000066;} +.yui-syntax-highlight .html4strict .es0 {color: #000099; font-weight: bold;} +.yui-syntax-highlight .html4strict .br0 {color: #66cc66;} +.yui-syntax-highlight .html4strict .sy0 {color: #66cc66;} +.yui-syntax-highlight .html4strict .st0 {color: #ff0000;} +.yui-syntax-highlight .html4strict .nu0 {color: #cc66cc;} +.yui-syntax-highlight .html4strict .sc-1 {color: #808080; font-style: italic;} +.yui-syntax-highlight .html4strict .sc0 {color: #00bbdd;} +.yui-syntax-highlight .html4strict .sc1 {color: #ddbb00;} +.yui-syntax-highlight .html4strict .sc2 {color: #009900;} +.yui-syntax-highlight .html4strict span.xtra { display:block; } + +/* Javascript Colors */ +.yui-syntax-highlight .javascript {font-family:monospace;} +.yui-syntax-highlight .javascript .imp {font-weight: bold; color: red;} +.yui-syntax-highlight .javascript .kw1 {color: #000066; font-weight: bold;} +.yui-syntax-highlight .javascript .kw2 {color: #003366; font-weight: bold;} +.yui-syntax-highlight .javascript .kw3 {color: #000066;} +.yui-syntax-highlight .javascript .co1 {color: #006600; font-style: italic;} +.yui-syntax-highlight .javascript .co2 {color: #009966; font-style: italic;} +.yui-syntax-highlight .javascript .coMULTI {color: #006600; font-style: italic;} +.yui-syntax-highlight .javascript .es0 {color: #000099; font-weight: bold;} +.yui-syntax-highlight .javascript .br0 {color: #009900;} +.yui-syntax-highlight .javascript .sy0 {color: #339933;} +.yui-syntax-highlight .javascript .st0 {color: #3366CC;} +.yui-syntax-highlight .javascript .nu0 {color: #CC0000;} +.yui-syntax-highlight .javascript .me1 {color: #660066;} +.yui-syntax-highlight .javascript span.xtra { display:block; } + +/* CSS Colors */ +.yui-syntax-highlight .css {font-family:monospace;} +.yui-syntax-highlight .css .imp {font-weight: bold; color: red;} +.yui-syntax-highlight .css .kw1 {color: #000000; font-weight: bold;} +.yui-syntax-highlight .css .kw2 {color: #993333;} +.yui-syntax-highlight .css .co1 {color: #a1a100;} +.yui-syntax-highlight .css .co2 {color: #ff0000; font-style: italic;} +.yui-syntax-highlight .css .coMULTI {color: #808080; font-style: italic;} +.yui-syntax-highlight .css .es0 {color: #000099; font-weight: bold;} +.yui-syntax-highlight .css .br0 {color: #00AA00;} +.yui-syntax-highlight .css .sy0 {color: #00AA00;} +.yui-syntax-highlight .css .st0 {color: #ff0000;} +.yui-syntax-highlight .css .nu0 {color: #cc66cc;} +.yui-syntax-highlight .css .re0 {color: #cc00cc;} +.yui-syntax-highlight .css .re1 {color: #6666ff;} +.yui-syntax-highlight .css .re2 {color: #3333ff;} +.yui-syntax-highlight .css .re3 {color: #933;} +.yui-syntax-highlight .css span.xtra { display:block; } + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.gif new file mode 100644 index 0000000000000000000000000000000000000000..5033ff576c02636bc8bbe69addcf7751861bab20 GIT binary patch literal 5901 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 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/ajax-loader.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe2cd23b3a3c017ae6acfd291135a998e2f8ee74 GIT binary patch literal 3208 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 C|Ftdv literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/asc.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/asc.gif new file mode 100644 index 0000000000000000000000000000000000000000..a1fe7385d5ac940629233f0dc4bbd61f20959c3b GIT binary patch literal 177 zcmZ?wbhEHbU}|FG@8_44nAqLjosyCg9vmZ){{V zVZwy=_I7V?@1UTd{Jgy0-d;-!i@3Nr8*A&jy1Ge|CjI~ap8*F@{K>+|z#z_`1Cj^X z$-t`jKsD}w@w|)+IvTGc!Y=lCF}Yu=Q8eH=%k0e0mLc1=fuZY=!y%64o~d4Qx%?Cv FtO0P~GlKvC literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/autocomplete.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/autocomplete.css new file mode 100644 index 0000000..54541c5 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/autocomplete.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-skin-sam .yui-ac{position:relative;font-family:arial;font-size:100%}.yui-skin-sam .yui-ac-input{position:absolute;width:100%}.yui-skin-sam .yui-ac-container{position:absolute;top:1.6em;width:100%}.yui-skin-sam .yui-ac-content{position:absolute;width:100%;border:1px solid #808080;background:#fff;overflow:hidden;z-index:9050}.yui-skin-sam .yui-ac-shadow{position:absolute;margin:.3em;width:100%;background:#000;-moz-opacity:.10;opacity:.10;filter:alpha(opacity=10);z-index:9049}.yui-skin-sam .yui-ac iframe{opacity:0;filter:alpha(opacity=0);padding-right:.3em;padding-bottom:.3em}.yui-skin-sam .yui-ac-content ul{margin:0;padding:0;width:100%}.yui-skin-sam .yui-ac-content li{margin:0;padding:2px 5px;cursor:default;white-space:nowrap;list-style:none;zoom:1}.yui-skin-sam .yui-ac-content li.yui-ac-prehighlight{background:#b3d4ff}.yui-skin-sam .yui-ac-content li.yui-ac-highlight{background:#426fd9;color:#FFF} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-h.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-h.png new file mode 100644 index 0000000000000000000000000000000000000000..5f69f4e2564357c83eddcecd5f104e14ecf09d49 GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0vp^8bBP#!2~4rHx?TMDaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(ehe3dtTpz6=aiY77hwEes65fIoOOtf|Nms9M{<~TG{NqzV`0JLv$@3}2r!1e&d7^!S-DO!ayYtzu zlYbXZdwJtvz~-c)`W2~GWd>K)%(x?;HM38a$5dPGdwUdyvi-fkSZmx?=65Sx>H+$T N!PC{xWt~$(695Wxh_(O# literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-v.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-v.png new file mode 100644 index 0000000000000000000000000000000000000000..658574a9d560febf6f58a6a005e602ae734f97da GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^fk3Rm!2~2Z4>V?gr~;43Vg?4j!ywFfJby(BP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzCyA`kS_y6l^O#>Lkk1LFQ8Dv3kHT#0|tgy z2@DKYGZ+}e3+C(!v;j)&_H=O!$#8xetNtMognoD1W&+apvb;IkbSm6HPD+>;$YzUet;PS1vwR5kn@U@xAZc*X`bN{qf6~>%I#YFG@c*bNAWmV~4vw71T)EP4+yI zm~wtolli{h{KvO{m;tHh|I%4jCy1_T3f;gJc5v07ee4g7Yue6#khD9T{)1zz`*b-fq}tl1_Oh5!JJ)zHb9Bj zo-U3d8P0E~+HyA*iX83NS6;e=XVR0zjVBT|NT_&L{`FGpKAL2Fa>10KxKFts1mAI{ zTl(++c+cBw&>1Hg`q?f)-lTL;*t$N(e z5?hd3GOgj$2NlMp2LqYB{x-9SR9ACql#~mV9Q=7MjH&2tFH1^vHs=YGaG?o#I;s{w z@^7uZwW|JFk^J=j)5pJVtzYr_iPcWOb;5U<>=m}`da)?fz4zkhFyGbPdQqiUBy97q c5+S&cLBv9~EU0~*E702vp00i_>zopr03oxJMgRZ+ literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-v.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-v.png new file mode 100644 index 0000000000000000000000000000000000000000..2efd664d9abdddff7e06ec512e0198f5fcaf1a56 GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^0YI$5!2~3qF}(@{Qk(@Ik;M!Qe1}1p@p%4<6rdnu zage(c!@6@aFM%AEbVpxD28NCO+{4xi!)|R=d;J&iHZ8yvVO_gGSA|3s-364JloT@b e|NoWUGS9D3dxyvWMZl0`VDNPHb6Mw<&;$VKhMGhG literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-h.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-h.gif new file mode 100644 index 0000000000000000000000000000000000000000..996288916e82bf2972bb4b8097f1b4a0869955d2 GIT binary patch literal 212 zcmV;_04x7TNk%w1VbK5_0HOu};o;%Q$;qdur-_M)x3{;~*Vq65{{R30A^8LW000I6 zEC2ui0MP&(000A-Xu90~Fv>}*y*TU5yZ>M)j$~<`XsWJk>%MR-&vb3yc&_h!@BhG{ za7Zi~kI1BQ$!t1BgQ#>$ty-_xtai)odcWYXI4gJ*&gisy&2GEj@VIs;jK6uCK7M Ova__cwzs%A2>?48g>Yp6 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-v.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-v.gif new file mode 100644 index 0000000000000000000000000000000000000000..8e287cd52222c75c8f921cfdd4b4ae02b783c0e4 GIT binary patch literal 481 zcmV<70UrKGNk%w1VI%+9?F_4V!T?c3Yi)6>)G>FKw(x2LD4*Voto|Nj60 z00000000000000000000A^8LW000R9EC2ui03-n5000F4Fv&@)y*TU5yZ>M)1%db# z2qKu>ks2)LB5`naUe$Rb%^?jF5?t^_yflh-^g;Ix9iB^kPjarXfkzSKvm137eG4lFF3Kmd=>a zn$n!qo;kDDqu96FtKO~LyW+j%zvjW{!|KKC$L`7S%ks_i&-T&y)B4r?*Pu#pof4P| zTr7Xv0HRt$kfFg^2){)Pr?BA>i=iIons~6H#(^J>3vz_$apcC5C`(}s7}B9hkS|51 zeAV(|&5SW!&diq6W>1_uyZvN2bfM3n002t}0{{R350Hx300004XF*Lt007q5 z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzfKW_SMepzL z*?5)vnXr^-@mq~v#Is<_TJv!tH9IQe$@Xx30Dl4m?CIp{=H9&7-_qpj z@$&Na_V>}=-P_s8t;X5r<>9oxu=V))t;fI5&dBfV=di}q&Ctl)z^}#1!s6l2^YQNR z_4fPy{pIZK+vn}2t)%$)_toO#;n%^Nt);HK#<#b(?d|Q^-PrN-^x)*+!OF_W$Hdm! z)7aL|?e6dH@9^Q?*SNj5^z`$uytMfH`|DE_v7Q^$@+uYl) zwyn<6!SC?!+19@4>g)FN@VIM;P5=N05J^NqRCwC#*lSzbSQiFhNFotI4oL6_;vuC{b=qK$I+Xz#Vv+gl@7g<|P-q!D?T7b6AA7YNE^pUbd+%Us zvHiGMY?dFDpVm+7|H0xQ7NY(A7RQyM(T<>!bm{vn3=x8=(rL;Q{SFI3)s8?qX$u8u zH@N?3nH4ckx}#Azn*N_G4oMxo<@6I6%H5fJK~aq=_stfD8jQ*iH3XfEFQlfX+!}Qx ze4~YjL@+!_3T(FWE&nOEIN%yOC)PU~H4MJ1yg;_~-0+z22Q16&6NVKzRfjwP1ed_zA3i zg*8U*O1&IMRBp?=xVZQmEHTY-U$r_!L!g-&bz+X`4t(d)WtnwhDFsip&8{Fwn?C$Y-BAJXOA#XK`_RhKI zdKm{RiY;3Snxy>@I2z;yA7(lgGa&E3x|;RV@bB*M9w! z+hA1ns)v#B*^{x*P0SkNT`$lbbO1 zME0ERVyeQj0n}Jv{oq}t;(WYbiBc-f4zs z%YX#}iTOaK;&}X+uf*nSwGJ!E(%mmvP#Eld++;eN$nw9l&R$elfpTnqJ`jt=_)zHh zEEWjIGmI!o&9${JSS8e?pJ6B}4r^%JRure>NuS5FsBIQf4$MD%o3GdOr9Z`r)$Fow z_7)3VDR7fVlvd3Kp3iKn%Jc0jXMc6DrhK_F|4%-@l8@I9{bf-Uea+=ztJ|c9(jI1G zjt{S#Wi`}ip(Oz5kGJ*uO1}QgL#nr|KKb+-)^Zv0xdlz4EyieCK9N;l&1@?$nkRkI zSpY%x{7TzHPCj@rJzbDxabu|&{B_W>aAuQjDtG_l{MF3NbN(t6a;hq(proTr9lj3V zFq0r5Yr-dqvS?jj9=41o8G*_@Oz2l1W@es%^_*o@Cx4b`zeP~{jbE9ZeqdyJV#4Q> zcK=@cLS3bf(PX@q&t4#FW;+xLIh6BCDV)h*M_W5O-6I^ zL?8rB&V;tNuN?bn1f}hMwYen95?IsymMq;u*q~)LN$27Z%ZlT}hgTuT?)!Qs9B$j` zgJRKfeJYExuV7lxqE&?1e{`%aFGmI}i`gU@j)%|Al&f{!0waQoXeKxtSzcSc=lJLY zYXVg^ZH!*rXx>|0jYJ~1;VRVWv$_`xBA>}7|7fET?R99Lt{%b>#H8%gO_B=Uv2 zEZr;OVLH8+?g$J?!XH~++cT_UbLr`l3|9xAPn1NT3|sX&7z{>cA%k_9O)_L-@4W|< zR;$G@Dz;|L6tAUISrR2!1W~qb$W})LQ?s{UYyQtI+$4M+`FW=0_tP{y=53kUUc{s# zj)J%$iGRI26*pvgbU}c}Bv|dpn337yda&vH^B^dlvL7Yi z@mSG(V{GAdZNNf>0fr$@qv3(QOWMNm!`ZQ3CJP5+#k*3l*t}Kjy}A=0vY@brM-Tu) zpX+wmyQJ-?{;c0BBEdO{9*y-|@c|18>k#HI2%TyNO^>vt!|h)Na{HGz1Fvj_hb{D5 zJ%*wsV*087z%uTCq5yIDOd+dU>g5^AA;fan9>~#P zUFIDp*E^prm1K-f+YNrkz>AFelrhp8wtB(G0M676;-~cnG0H;6K!E*vgTNlL6VXu? z+HC^fZvPTp7aBxoqy?Xu1lqCx9<&{!C2rKcXsJrvG#yNhy03)|QoT{41~uw_oBM|R k{QsPv*4L~bm;VVc0HT!-jb!e$TmS$707*qoM6N<$g7zKgCjbBd literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/button.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/button.css new file mode 100644 index 0000000..c54fc72 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/button.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-button{display:-moz-inline-box;display:inline-block;vertical-align:text-bottom;}.yui-button .first-child{display:block;*display:inline-block;}.yui-button button,.yui-button a{display:block;*display:inline-block;border:none;margin:0;}.yui-button button{background-color:transparent;*overflow:visible;cursor:pointer;}.yui-button a{text-decoration:none;}.yui-skin-sam .yui-button{border-width:1px 0;border-style:solid;border-color:#808080;background:url(sprite.png) repeat-x 0 0;margin:auto .25em;}.yui-skin-sam .yui-button .first-child{border-width:0 1px;border-style:solid;border-color:#808080;margin:0 -1px;_margin:0;}.yui-skin-sam .yui-button button,.yui-skin-sam .yui-button a,.yui-skin-sam .yui-button a:visited{padding:0 10px;font-size:93%;line-height:2;*line-height:1.7;min-height:2em;*min-height:auto;color:#000;}.yui-skin-sam .yui-button a{*line-height:1.875;*padding-bottom:1px;}.yui-skin-sam .yui-split-button button,.yui-skin-sam .yui-menu-button button{padding-right:20px;background-position:right center;background-repeat:no-repeat;}.yui-skin-sam .yui-menu-button button{background-image:url(menu-button-arrow.png);}.yui-skin-sam .yui-split-button button{background-image:url(split-button-arrow.png);}.yui-skin-sam .yui-button-focus{border-color:#7D98B8;background-position:0 -1300px;}.yui-skin-sam .yui-button-focus .first-child{border-color:#7D98B8;}.yui-skin-sam .yui-split-button-focus button{background-image:url(split-button-arrow-focus.png);}.yui-skin-sam .yui-button-hover{border-color:#7D98B8;background-position:0 -1300px;}.yui-skin-sam .yui-button-hover .first-child{border-color:#7D98B8;}.yui-skin-sam .yui-split-button-hover button{background-image:url(split-button-arrow-hover.png);}.yui-skin-sam .yui-button-active{border-color:#7D98B8;background-position:0 -1700px;}.yui-skin-sam .yui-button-active .first-child{border-color:#7D98B8;}.yui-skin-sam .yui-split-button-activeoption{border-color:#808080;background-position:0 0;}.yui-skin-sam .yui-split-button-activeoption .first-child{border-color:#808080;}.yui-skin-sam .yui-split-button-activeoption button{background-image:url(split-button-arrow-active.png);}.yui-skin-sam .yui-radio-button-checked,.yui-skin-sam .yui-checkbox-button-checked{border-color:#304369;background-position:0 -1400px;}.yui-skin-sam .yui-radio-button-checked .first-child,.yui-skin-sam .yui-checkbox-button-checked .first-child{border-color:#304369;}.yui-skin-sam .yui-radio-button-checked button,.yui-skin-sam .yui-checkbox-button-checked button{color:#fff;}.yui-skin-sam .yui-button-disabled{border-color:#ccc;background-position:0 -1500px;}.yui-skin-sam .yui-button-disabled .first-child{border-color:#ccc;}.yui-skin-sam .yui-button-disabled button,.yui-skin-sam .yui-button-disabled a,.yui-skin-sam .yui-button-disabled a:visited{color:#A6A6A6;cursor:default;}.yui-skin-sam .yui-menu-button-disabled button{background-image:url(menu-button-arrow-disabled.png);}.yui-skin-sam .yui-split-button-disabled button{background-image:url(split-button-arrow-disabled.png);} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/calendar.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/calendar.css new file mode 100644 index 0000000..df1d705 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/calendar.css @@ -0,0 +1,8 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-calcontainer{position:relative;float:left;_overflow:hidden}.yui-calcontainer iframe{position:absolute;border:0;margin:0;padding:0;z-index:0;width:100%;height:100%;left:0;top:0}.yui-calcontainer iframe.fixedsize{width:50em;height:50em;top:-1px;left:-1px}.yui-calcontainer.multi .groupcal{z-index:1;float:left;position:relative}.yui-calcontainer .title{position:relative;z-index:1}.yui-calcontainer .close-icon{position:absolute;z-index:1;text-indent:-10000em;overflow:hidden}.yui-calendar{position:relative}.yui-calendar .calnavleft{position:absolute;z-index:1;text-indent:-10000em;overflow:hidden}.yui-calendar .calnavright{position:absolute;z-index:1;text-indent:-10000em;overflow:hidden}.yui-calendar .calheader{position:relative;width:100%;text-align:center}.yui-calcontainer .yui-cal-nav-mask{position:absolute;z-index:2;margin:0;padding:0;width:100%;height:100%;_width:0;_height:0;left:0;top:0;display:none}.yui-calcontainer .yui-cal-nav{position:absolute;z-index:3;top:0;display:none}.yui-calcontainer .yui-cal-nav .yui-cal-nav-btn{display:-moz-inline-box;display:inline-block}.yui-calcontainer .yui-cal-nav .yui-cal-nav-btn button{display:block;*display:inline-block;*overflow:visible;border:0;background-color:transparent;cursor:pointer}.yui-calendar .calbody a:hover{background:inherit}p#clear{clear:left;padding-top:10px}.yui-skin-sam .yui-calcontainer{background-color:#f2f2f2;border:1px solid #808080;padding:10px}.yui-skin-sam .yui-calcontainer.multi{padding:0 5px 0 5px}.yui-skin-sam .yui-calcontainer.multi .groupcal{background-color:transparent;border:0;padding:10px 5px 10px 5px;margin:0}.yui-skin-sam .yui-calcontainer .title{background:url(sprite.png) repeat-x 0 0;border-bottom:1px solid #ccc;font:100% sans-serif;color:#000;font-weight:bold;height:auto;padding:.4em;margin:0 -10px 10px -10px;top:0;left:0;text-align:left}.yui-skin-sam .yui-calcontainer.multi .title{margin:0 -5px 0 -5px}.yui-skin-sam .yui-calcontainer.withtitle{padding-top:0}.yui-skin-sam .yui-calcontainer .calclose{background:url(sprite.png) no-repeat 0 -300px;width:25px;height:15px;top:.4em;right:.4em;cursor:pointer}.yui-skin-sam .yui-calendar{border-spacing:0;border-collapse:collapse;font:100% sans-serif;text-align:center;margin:0}.yui-skin-sam .yui-calendar .calhead{background:transparent;border:0;vertical-align:middle;padding:0}.yui-skin-sam .yui-calendar .calheader{background:transparent;font-weight:bold;padding:0 0 .6em 0;text-align:center}.yui-skin-sam .yui-calendar .calheader img{border:0}.yui-skin-sam .yui-calendar .calnavleft{background:url(sprite.png) no-repeat 0 -450px;width:25px;height:15px;top:0;bottom:0;left:-10px;margin-left:.4em;cursor:pointer}.yui-skin-sam .yui-calendar .calnavright{background:url(sprite.png) no-repeat 0 -500px;width:25px;height:15px;top:0;bottom:0;right:-10px;margin-right:.4em;cursor:pointer}.yui-skin-sam .yui-calendar .calweekdayrow{height:2em}.yui-skin-sam .yui-calendar .calweekdayrow th{padding:0;border:0}.yui-skin-sam .yui-calendar .calweekdaycell{color:#000;font-weight:bold;text-align:center;width:2em}.yui-skin-sam .yui-calendar .calfoot{background-color:#f2f2f2}.yui-skin-sam .yui-calendar .calrowhead,.yui-skin-sam .yui-calendar .calrowfoot{color:#a6a6a6;font-size:85%;font-style:normal;font-weight:normal;border:0}.yui-skin-sam .yui-calendar .calrowhead{text-align:right;padding:0 2px 0 0}.yui-skin-sam .yui-calendar .calrowfoot{text-align:left;padding:0 0 0 2px}.yui-skin-sam .yui-calendar td.calcell{border:1px solid #ccc;background:#fff;padding:1px;height:1.6em;line-height:1.6em;text-align:center;white-space:nowrap}.yui-skin-sam .yui-calendar td.calcell a{color:#06c;display:block;height:100%;text-decoration:none}.yui-skin-sam .yui-calendar td.calcell.today{background-color:#000}.yui-skin-sam .yui-calendar td.calcell.today a{background-color:#fff}.yui-skin-sam .yui-calendar td.calcell.oom{background-color:#ccc;color:#a6a6a6;cursor:default}.yui-skin-sam .yui-calendar td.calcell.oom a{color:#a6a6a6}.yui-skin-sam .yui-calendar td.calcell.selected{background-color:#fff;color:#000}.yui-skin-sam .yui-calendar td.calcell.selected a{background-color:#b3d4ff;color:#000}.yui-skin-sam .yui-calendar td.calcell.calcellhover{background-color:#426fd9;color:#fff;cursor:pointer}.yui-skin-sam .yui-calendar td.calcell.calcellhover a{background-color:#426fd9;color:#fff}.yui-skin-sam .yui-calendar td.calcell.previous{color:#e0e0e0}.yui-skin-sam .yui-calendar td.calcell.restricted{text-decoration:line-through}.yui-skin-sam .yui-calendar td.calcell.highlight1{background-color:#cf9}.yui-skin-sam .yui-calendar td.calcell.highlight2{background-color:#9cf}.yui-skin-sam .yui-calendar td.calcell.highlight3{background-color:#fcc}.yui-skin-sam .yui-calendar td.calcell.highlight4{background-color:#cf9}.yui-skin-sam .yui-calendar a.calnav{border:1px solid #f2f2f2;padding:0 4px;text-decoration:none;color:#000;zoom:1}.yui-skin-sam .yui-calendar a.calnav:hover{background:url(sprite.png) repeat-x 0 0;border-color:#a0a0a0;cursor:pointer}.yui-skin-sam .yui-calcontainer .yui-cal-nav-mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui-skin-sam .yui-calcontainer .yui-cal-nav{font-family:arial,helvetica,clean,sans-serif;font-size:93%;border:1px solid #808080;left:50%;margin-left:-7em;width:14em;padding:0;top:2.5em;background-color:#f2f2f2}.yui-skin-sam .yui-calcontainer.withtitle .yui-cal-nav{top:4.5em}.yui-skin-sam .yui-calcontainer.multi .yui-cal-nav{width:16em;margin-left:-8em}.yui-skin-sam .yui-calcontainer .yui-cal-nav-y,.yui-skin-sam .yui-calcontainer .yui-cal-nav-m,.yui-skin-sam .yui-calcontainer .yui-cal-nav-b{padding:5px 10px 5px 10px}.yui-skin-sam .yui-calcontainer .yui-cal-nav-b{text-align:center}.yui-skin-sam .yui-calcontainer .yui-cal-nav-e{margin-top:5px;padding:5px;background-color:#edf5ff;border-top:1px solid black;display:none}.yui-skin-sam .yui-calcontainer .yui-cal-nav label{display:block;font-weight:bold} +.yui-skin-sam .yui-calcontainer .yui-cal-nav-mc{width:100%;_width:auto}.yui-skin-sam .yui-calcontainer .yui-cal-nav-y input.yui-invalid{background-color:#ffee69;border:1px solid #000}.yui-skin-sam .yui-calcontainer .yui-cal-nav-yc{width:4em}.yui-skin-sam .yui-calcontainer .yui-cal-nav .yui-cal-nav-btn{border:1px solid #808080;background:url(sprite.png) repeat-x 0 0;background-color:#ccc;margin:auto .15em}.yui-skin-sam .yui-calcontainer .yui-cal-nav .yui-cal-nav-btn button{padding:0 8px;font-size:93%;line-height:2;*line-height:1.7;min-height:2em;*min-height:auto;color:#000}.yui-skin-sam .yui-calcontainer .yui-cal-nav .yui-cal-nav-btn.yui-default{border:1px solid #304369;background-color:#426fd9;background:url(sprite.png) repeat-x 0 -1400px}.yui-skin-sam .yui-calcontainer .yui-cal-nav .yui-cal-nav-btn.yui-default button{color:#fff} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/carousel.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/carousel.css new file mode 100644 index 0000000..b3d86a6 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/carousel.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-carousel{visibility:hidden;overflow:hidden;position:relative;text-align:left;zoom:1;}.yui-carousel.yui-carousel-visible{visibility:visible;}.yui-carousel-content{overflow:hidden;position:relative;text-align:center;}.yui-carousel-element li{border:1px solid #ccc;list-style:none;margin:1px;overflow:hidden;padding:0;position:absolute;text-align:center;}.yui-carousel-vertical .yui-carousel-element li{display:block;float:none;}.yui-log .carousel{background:#f2e886;}.yui-carousel-nav{zoom:1;}.yui-carousel-nav:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.yui-carousel-button-focus{outline:1px dotted #000;}.yui-carousel-min-width{min-width:115px;}.yui-carousel-element{overflow:hidden;position:relative;margin:0 auto;padding:0;text-align:left;*margin:0;}.yui-carousel-horizontal .yui-carousel-element{width:320000px;}.yui-carousel-vertical .yui-carousel-element{height:320000px;}.yui-skin-sam .yui-carousel-nav select{position:static;}.yui-carousel .yui-carousel-item-selected{border:1px dashed #000;margin:1px;}.yui-skin-sam .yui-carousel,.yui-skin-sam .yui-carousel-vertical{border:1px solid #808080;}.yui-skin-sam .yui-carousel-nav{background:url(sprite.png) repeat-x 0 0;padding:3px;text-align:right;}.yui-skin-sam .yui-carousel-button{background:url(sprite.png) no-repeat 0 -600px;float:right;height:19px;margin:5px;overflow:hidden;width:40px;}.yui-skin-sam .yui-carousel-vertical .yui-carousel-button{background-position:0 -800px;}.yui-skin-sam .yui-carousel-button-disabled{background-position:0 -2000px;}.yui-skin-sam .yui-carousel-vertical .yui-carousel-button-disabled{background-position:0 -2100px;}.yui-skin-sam .yui-carousel-button input,.yui-skin-sam .yui-carousel-button button{background-color:transparent;border:0;cursor:pointer;display:block;height:44px;margin:-2px 0 0 -2px;padding:0 0 0 50px;}.yui-skin-sam span.yui-carousel-first-button{background-position:0 -550px;margin-left:-100px;margin-right:50px;*margin:5px 5px 5px -90px;}.yui-skin-sam .yui-carousel-vertical span.yui-carousel-first-button{background-position:0 -750px;}.yui-skin-sam span.yui-carousel-first-button-disabled{background-position:0 -1950px;}.yui-skin-sam .yui-carousel-vertical span.yui-carousel-first-button-disabled{background-position:0 -2050px;}.yui-skin-sam .yui-carousel-nav ul{float:right;height:19px;margin:0;margin-left:-220px;margin-right:100px;*margin-left:-160px;*margin-right:0;padding:0;}.yui-skin-sam .yui-carousel-min-width .yui-carousel-nav ul{*margin-left:-170px;}.yui-skin-sam .yui-carousel-nav select{position:relative;*right:50px;top:4px;}.yui-skin-sam .yui-carousel-vertical .yui-carousel-nav select{position:static;}.yui-skin-sam .yui-carousel-vertical .yui-carousel-nav ul,.yui-skin-sam .yui-carousel-vertical .yui-carousel-nav select{float:none;margin:0;*zoom:1;}.yui-skin-sam .yui-carousel-nav ul li{background:url(sprite.png) no-repeat 0 -650px;cursor:pointer;float:left;height:9px;list-style:none;margin:10px 0 0 5px;overflow:hidden;padding:0;width:9px;}.yui-skin-sam .yui-carousel-nav ul:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.yui-skin-sam .yui-carousel-nav ul li a{display:block;width:100%;height:100%;text-indent:-10000px;text-align:left;overflow:hidden;}.yui-skin-sam .yui-carousel-nav ul li.yui-carousel-nav-page-focus{outline:1px dotted #000;}.yui-skin-sam .yui-carousel-nav ul li.yui-carousel-nav-page-selected{background-position:0 -700px;}.yui-skin-sam .yui-carousel-item-loading{background:url(ajax-loader.gif) no-repeat 50% 50%;position:absolute;text-indent:-150px;} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check0.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check0.gif new file mode 100644 index 0000000000000000000000000000000000000000..193028b99361c6527f17a9056037f3d8729fada7 GIT binary patch literal 608 zcmZ?wbhEHb6krfzc;>|L^y$-=FJFHD{{8v$=l}lwYiw-%_U+rNSFb*Q{ycHwL|t9o z4nyho27-Mo48_U+qq=FHi!VMBd=eR6X0+O=zU@7{g=`t?<-R$aV!QBO~=si|q# zu3gWbJ!@`mzI^%e$A3uKV-Me@C^y%BTZ(p%u#nr1TIw0qR;)H>HZ-Y})b4zPm zdq-zicTcmUtRf$uChJr_107k%CMHe`N0x;P`5omrrJC4T89CNEtasp8#oolg$!xcC z*G^_mh9((lImRPL*@bMRWts#ebZswOyr3>2&}6S{Yk&KWy@0BkeG`wFo;Jga7tBID z3Or5XCSs!Nxxa8b*r|v&i3p1^@tiSGSg@dh)kuRwD&VlggmwY>tRDsr6B@;pN)`kN kI5!@bwak+c_`=}P#wi$N7O_%^c>;TH(y2L>8UhT~0GYwkU;qFB literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check1.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check1.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d9ceba3847ffb41864626de755147cf2e0ccc41 GIT binary patch literal 622 zcmZ?wbhEHb6krfzcoxU7ckkYV2M?Y-d-m9|V>@>2*tTt3LPEl(O`BR;T8=%(xpqq#l;5>99Xq#)&2YTYiepbIy&0g+AOW@ zckS9Guc-F@`}d~imPLyeZQs6~fsu`YfvK{pX2F65U0q$Rt*sL$O-@Ws1A@}h((LT) z?(XjO>(?(?vSiJgH4`UJK6B=bk&)5y`M-)|l9Y<;$0E z*|Mdlr)S-|b(NKs3l=PFZf@Sadv|qB-H{_lmMvRWUS2+J+H@9n9wt`q{DLAwL&J0D z&M`1B06hgHX$=&AvM@3*#4+fAECR&|1N-TQIAB<`wzYS3c6IkOiz~=+aJchM|1mCdzDLXw4hE#vxNR(VN@CJ{DPhF!b7VuM)OM4A+ZRauU+7{|s2 zcnd2w$tde{Md^hbMtE?UD9bddsdKr+>S#rp``L#2t2OayvU`dd#ftf`8raM6HSzlj zc(5=uIVZF*Fl5;XgfOzUFmkr3NH`Qau*iwBl%AN_(0#mLZsnU73LZ^-il>A0j5i(a fVsVr<>G*MA!L!EM+AbM4F05F7ettU>BZD;n{1fhr literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check2.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check2.gif new file mode 100644 index 0000000000000000000000000000000000000000..181317599bfd45f03a7a69784b232509171d98e9 GIT binary patch literal 609 zcmZ?wbhEHb6krfzc;?HnW5@{Q2|Z;^P1R|37;4=+mc9 z2M!#ludjdl^y!^DcW&Oi`QX8Wd-v|GTD9u_{rlg(eY<=2?(*f!7cE+}Zr!@3rlz#C zw93lLty{Ntbad?6wX3|me9f9QU0q#_jEvpg-8D5erKP3o*RL-ssmjjIK6B=bk&#hr zYwM9CN4|dj+Sb-)XlVHT`}dxnp5w=lFIlo=!GZ+|z~IZE19BTEP8ittHTX6)x3spkcXW1j_cTk$%W!aLa!=*3 zc9)lEa$s@xW?Hz=(p!newn>g(hVaPYrXndu(oIuG-2?s&?!;%&%Yb2pGtyHpw{(Nw4Sq&gU}|FG@8_44nAqLjosyCg9vmZ){{V zVZwy=_I7V?@1UTd{Jgy0-d;-!i@3Nr8*A&jy1Ge|CjI~ap8*F@{K>+|z#z_`1Cj^X z$-t_&AfWe&MeGaLh@5Q0kS;d8>Ju6P(#(BMdM*5_og0L@6jvQ6(g^H!doZ(#VTvMy FH2`14Gspk{ literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-dn.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-dn.png new file mode 100644 index 0000000000000000000000000000000000000000..85fda0bbca21cefc6b8cf1726bc83e43bff993c4 GIT binary patch literal 116 zcmeAS@N?(olHy`uVBq!ia0vp@K+M9#3?wzWV%32ZXMj(L>;M1%fy~Ir2;r~IJAo|5 zk|4ie28U-i(tsREPZ!6Kid)Guq>ddput17Y#X`7&C779+nL(zFDdZjVkv^az22WQ% Jmvv4FO#tWt9i9LH literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-up.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-up.png new file mode 100644 index 0000000000000000000000000000000000000000..1c674316aed41943dae79b01583956db63c8be08 GIT binary patch literal 116 zcmeAS@N?(olHy`uVBq!ia0vp@K+M9#3?wzWV%32ZXMj(L>;M1%fy}VT__niwAVJ2G zAirP+hi5m^fE-Cr7srr_TgeGo2?+@gd>DjQ2|6TYNiZ`ri2h~@(drDS1}b9kboFyt I=akR{0KC>mi#>Q#WroDds`uzFx3^1VhlZBCift5iABmh#&!0aEf z>&{2rQ#+d!lrGr5WpF;$+r>U-p%#pf7j6C(;=#aR4FLK*IpF{R literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite-active.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite-active.gif new file mode 100644 index 0000000000000000000000000000000000000000..3e9d4200b3e6b124354f12d6c5f90513587315d1 GIT binary patch literal 5614 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 RDPx!cToE9&k%xf2{{!Lm*)sqD literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite.gif new file mode 100644 index 0000000000000000000000000000000000000000..02042fa1474cd62d7de63588ae536f5495d45be2 GIT binary patch literal 5690 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 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor.css new file mode 100644 index 0000000..d3cde1c --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor.css @@ -0,0 +1,10 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-busy{cursor:wait!important;}.yui-toolbar-container fieldset,.yui-editor-container fieldset{padding:0;margin:0;border:0;}.yui-toolbar-container legend{display:none;}.yui-skin-sam .yui-toolbar-container .yui-button button,.yui-skin-sam .yui-toolbar-container .yui-button a,.yui-skin-sam .yui-toolbar-container .yui-button a:visited{font-size:0;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-select button,.yui-skin-sam .yui-toolbar-container .yui-toolbar-select a,.yui-skin-sam .yui-toolbar-container .yui-toolbar-select a:visited,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton button,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a:visited{font-size:12px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.up,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.down{font-size:0;line-height:0;padding:0;}.yui-toolbar-container .yui-toolbar-subcont{padding:.25em 0;zoom:1;}.yui-toolbar-container-collapsed .yui-toolbar-subcont{display:none;}.yui-toolbar-container .yui-toolbar-subcont:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-container span.yui-toolbar-draghandle{cursor:move;border-left:1px solid #999;border-right:1px solid #999;overflow:hidden;text-indent:77777px;width:2px;height:20px;display:block;clear:none;float:left;margin:0 0 0 .2em;}.yui-toolbar-container .yui-toolbar-titlebar.draggable{cursor:move;}.yui-toolbar-container .yui-toolbar-titlebar{position:relative;}.yui-toolbar-container .yui-toolbar-titlebar h2{font-weight:bold;letter-spacing:0;border:none;color:#000;margin:0;padding:.2em;}.yui-toolbar-container .yui-toolbar-titlebar h2 a{text-decoration:none;color:#000;cursor:default;}.yui-toolbar-container.yui-toolbar-grouped span.yui-toolbar-draghandle{height:40px;}.yui-toolbar-container .yui-toolbar-group{float:left;margin-right:.5em;zoom:1;}.yui-toolbar-container .yui-toolbar-group:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-container .yui-toolbar-group h3{font-size:75%;padding:0 0 0 .25em;margin:0;}.yui-toolbar-container span.yui-toolbar-separator{width:2px;padding:0;height:18px;margin:.2em 0 .2em .1em;display:none;float:left;}.yui-toolbar-container.yui-toolbar-grouped span.yui-toolbar-separator{height:45px;*height:50px;}.yui-toolbar-container.yui-toolbar-grouped .yui-toolbar-group span.yui-toolbar-separator{height:18px;display:block;}.yui-toolbar-container ul li{margin:0;padding:0;list-style-type:none;}.yui-toolbar-container .yui-toolbar-nogrouplabels h3{display:none;}.yui-toolbar-container .yui-push-button,.yui-toolbar-container .yui-color-button,.yui-toolbar-container .yui-menu-button{position:relative;cursor:pointer;}.yui-toolbar-container .yui-button .first-child,.yui-toolbar-container .yui-button .first-child a{height:100%;width:100%;overflow:hidden;font-size:0;}.yui-toolbar-container .yui-button-disabled{cursor:default;}.yui-toolbar-container .yui-button-disabled .yui-toolbar-icon{opacity:.5;filter:alpha(opacity=50);}.yui-toolbar-container .yui-button-disabled .up,.yui-toolbar-container .yui-button-disabled .down{opacity:.5;filter:alpha(opacity=50);}.yui-toolbar-container .yui-button a{overflow:hidden;}.yui-toolbar-container .yui-toolbar-select .first-child a{cursor:pointer;}.yui-toolbar-fontname-arial{font-family:Arial;}.yui-toolbar-fontname-arial-black{font-family:Arial Black;}.yui-toolbar-fontname-comic-sans-ms{font-family:Comic Sans MS;}.yui-toolbar-fontname-courier-new{font-family:Courier New;}.yui-toolbar-fontname-times-new-roman{font-family:Times New Roman;}.yui-toolbar-fontname-verdana{font-family:Verdana;}.yui-toolbar-fontname-impact{font-family:Impact;}.yui-toolbar-fontname-lucida-console{font-family:Lucida Console;}.yui-toolbar-fontname-tahoma{font-family:Tahoma;}.yui-toolbar-fontname-trebuchet-ms{font-family:Trebuchet MS;}.yui-toolbar-container .yui-toolbar-spinbutton{position:relative;}.yui-toolbar-container .yui-toolbar-spinbutton .first-child a{z-index:0;opacity:1;}.yui-toolbar-container .yui-toolbar-spinbutton a.up,.yui-toolbar-container .yui-toolbar-spinbutton a.down{position:absolute;display:block;right:0;cursor:pointer;z-index:1;padding:0;margin:0;}.yui-toolbar-container .yui-overlay{position:absolute;}.yui-toolbar-container .yui-overlay ul li{margin:0;list-style-type:none;}.yui-toolbar-container{z-index:1;}.yui-editor-container .yui-editor-editable-container{position:relative;z-index:0;width:100%;}.yui-editor-container .yui-editor-masked{background-color:#CCC;height:100%;width:100%;position:absolute;top:0;left:0;opacity:.5;filter:alpha(opacity=50);}.yui-editor-container iframe{border:0;padding:0;margin:0;zoom:1;display:block;}.yui-editor-container .yui-editor-editable{padding:0;margin:0;}.yui-editor-container .dompath{font-size:85%;}.yui-editor-panel .hd{text-align:left;position:relative;}.yui-editor-panel .hd h3{font-weight:bold;padding:.25em 0 .25em .25em;margin:0;}.yui-editor-panel .bd{width:100%;zoom:1;position:relative;}.yui-editor-panel .bd div.yui-editor-body-cont{padding:.25em .1em;zoom:1;}.yui-editor-panel .bd .gecko form{overflow:auto;}.yui-editor-panel .bd div.yui-editor-body-cont:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-editor-panel .ft{text-align:right;width:99%;float:left;clear:both;}.yui-editor-panel .ft span.tip{display:block;position:relative;padding:.5em .5em .5em 23px;text-align:left;zoom:1;}.yui-editor-panel label{clear:both;float:left;padding:0;width:100%;text-align:left;zoom:1;}.yui-editor-panel .gecko label{overflow:auto;}.yui-editor-panel label strong{float:left;width:6em;}.yui-editor-panel .removeLink{width:80%;text-align:right;}.yui-editor-panel label input{margin-left:.25em;float:left;}.yui-editor-panel .yui-toolbar-group{margin-bottom:.75em;}.yui-editor-panel .height-width{float:left;}.yui-editor-panel .height-width span{font-style:italic;display:block;float:left;overflow:visible;}.yui-editor-panel .height-width span.info{font-size:70%;margin-top:3px;float:none;} +.yui-editor-panel .yui-toolbar-bordersize,.yui-editor-panel .yui-toolbar-bordertype{font-size:75%;}.yui-editor-panel .yui-toolbar-container span.yui-toolbar-separator{border:none;}.yui-editor-panel .yui-toolbar-bordersize span a span,.yui-editor-panel .yui-toolbar-bordertype span a span{display:block;height:8px;left:4px;position:absolute;top:3px;_top:-5px;width:24px;text-indent:52px;font-size:0;}.yui-editor-panel .yui-toolbar-bordertype span a span.yui-toolbar-bordertype-solid{border-bottom:1px solid black;}.yui-editor-panel .yui-toolbar-bordertype span a span.yui-toolbar-bordertype-dotted{border-bottom:1px dotted black;}.yui-editor-panel .yui-toolbar-bordertype span a span.yui-toolbar-bordertype-dashed{border-bottom:1px dashed black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-0{*top:0;text-indent:0;font-size:75%;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-1{border-bottom:1px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-2{border-bottom:2px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-3{top:2px;*top:-5px;border-bottom:3px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-4{top:1px;*top:-5px;border-bottom:4px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-5{top:1px;*top:-5px;border-bottom:5px solid black;}.yui-toolbar-container .yui-toolbar-bordersize-menu,.yui-toolbar-container .yui-toolbar-bordertype-menu{width:95px!important;}.yui-toolbar-bordersize-menu .yuimenuitemlabel,.yui-toolbar-bordertype-menu .yuimenuitemlabel,.yui-toolbar-bordersize-menu .yuimenuitemlabel,.yui-toolbar-bordertype-menu .yuimenuitemlabel:hover{margin:0 3px 7px 17px;}.yui-toolbar-bordersize-menu .yuimenuitemlabel .checkedindicator,.yui-toolbar-bordertype-menu .yuimenuitemlabel .checkedindicator{position:absolute;left:-12px;*top:14px;*left:0;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-1 a{border-bottom:1px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-2 a{border-bottom:2px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-3 a{border-bottom:3px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-4 a{border-bottom:4px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-5 a{border-bottom:5px solid black;height:14px;}.yui-toolbar-bordertype-menu li.yui-toolbar-bordertype-solid a{border-bottom:1px solid black;height:14px;}.yui-toolbar-bordertype-menu li.yui-toolbar-bordertype-dashed a{border-bottom:1px dashed black;height:14px;}.yui-toolbar-bordertype-menu li.yui-toolbar-bordertype-dotted a{border-bottom:1px dotted black;height:14px;}h2.yui-editor-skipheader,h3.yui-editor-skipheader{height:0;margin:0;padding:0;border:none;width:0;overflow:hidden;position:absolute;}.yui-toolbar-colors{width:133px;zoom:1;display:none;z-index:100;overflow:hidden;}.yui-toolbar-colors:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-colors a{height:9px;width:9px;float:left;display:block;overflow:hidden;text-indent:999px;margin:0;cursor:pointer;border:1px solid #F6F7EE;}.yui-toolbar-colors a:hover{border:1px solid black;}.yui-color-button-menu{overflow:visible;background-color:transparent;}.yui-toolbar-colors span{position:relative;display:block;padding:3px;overflow:hidden;float:left;width:100%;zoom:1;}.yui-toolbar-colors span:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-colors span em{height:35px;width:30px;float:left;display:block;overflow:hidden;text-indent:999px;margin:.75px;border:1px solid black;}.yui-toolbar-colors span strong{font-weight:normal;padding-left:3px;display:block;font-size:85%;float:left;width:65%;}.yui-toolbar-group-undoredo h3,.yui-toolbar-group-insertitem h3,.yui-toolbar-group-indentlist h3{width:68px;}.yui-toolbar-group-indentlist2 h3{width:122px;}.yui-toolbar-group-alignment h3{width:130px;}.yui-skin-sam .yui-editor-container{border:1px solid #808080;}.yui-skin-sam .yui-toolbar-container{zoom:1;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-titlebar{background:url(sprite.png) repeat-x 0 -200px;position:relative;}.yui-skin-sam .yui-editor-container .draggable .yui-toolbar-titlebar{cursor:move;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-titlebar h2{color:#000;font-weight:bold;margin:0;padding:.3em 1em;font-size:100%;text-align:left;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-group h3{color:#808080;font-size:75%;margin:1em 0 0;padding-bottom:0;padding-left:.25em;text-align:left;}.yui-toolbar-container span.yui-toolbar-separator{border:none;text-indent:33px;overflow:hidden;margin:0 .25em;}.yui-skin-sam .yui-toolbar-container{background-color:#F2F2F2;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-subcont{padding:0 1em .35em;border-bottom:1px solid #808080;}.yui-skin-sam .yui-toolbar-container-collapsed .yui-toolbar-titlebar{border-bottom:1px solid #808080;}.yui-skin-sam .yui-editor-container .visible .yui-menu-shadow,.yui-skin-sam .yui-editor-panel .visible .yui-menu-shadow{display:none;}.yui-skin-sam .yui-editor-container ul{list-style-type:none;margin:0;padding:0;}.yui-skin-sam .yui-editor-container ul li{list-style-type:none;margin:0;padding:0;}.yui-skin-sam .yui-toolbar-group ul li.yui-toolbar-groupitem{float:left;}.yui-skin-sam .yui-editor-container .dompath{background-color:#F2F2F2;border-top:1px solid #808080;color:#999;text-align:left;padding:.25em;}.yui-skin-sam .yui-toolbar-container .collapse{background:url(sprite.png) no-repeat 0 -400px;}.yui-skin-sam .yui-toolbar-container .collapsed{background:url(sprite.png) no-repeat 0 -350px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-titlebar span.collapse{cursor:pointer;position:absolute;top:4px;right:2px;display:block;overflow:hidden;height:15px;width:15px;text-indent:9999px;} +.yui-skin-sam .yui-toolbar-container .yui-push-button,.yui-skin-sam .yui-toolbar-container .yui-color-button,.yui-skin-sam .yui-toolbar-container .yui-menu-button{background:url(sprite.png) repeat-x 0 0;position:relative;display:block;height:22px;width:30px;_font-size:0;margin:0;border-color:#808080;color:#f2f2f2;border-style:solid;border-width:1px 0;zoom:1;}.yui-skin-sam .yui-toolbar-container .yui-push-button a,.yui-skin-sam .yui-toolbar-container .yui-color-button a,.yui-skin-sam .yui-toolbar-container .yui-menu-button a{padding-left:35px;height:20px;text-decoration:none;font-size:0;line-height:2;display:block;color:#000;overflow:hidden;white-space:nowrap;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a,.yui-skin-sam .yui-toolbar-container .yui-toolbar-select a{font-size:12px;}.yui-skin-sam .yui-toolbar-container .yui-push-button .first-child,.yui-skin-sam .yui-toolbar-container .yui-color-button .first-child,.yui-skin-sam .yui-toolbar-container .yui-menu-button .first-child{border-color:#808080;border-style:solid;border-width:0 1px;margin:0 -1px;display:block;position:relative;}.yui-skin-sam .yui-toolbar-container .yui-push-button-disabled .first-child,.yui-skin-sam .yui-toolbar-container .yui-color-button-disabled .first-child,.yui-skin-sam .yui-toolbar-container .yui-menu-button-disabled .first-child{border-color:#ccc;}.yui-skin-sam .yui-toolbar-container .yui-push-button-disabled a,.yui-skin-sam .yui-toolbar-container .yui-color-button-disabled a,.yui-skin-sam .yui-toolbar-container .yui-menu-button-disabled a{color:#A6A6A6;cursor:default;}.yui-skin-sam .yui-toolbar-container .yui-push-button-disabled,.yui-skin-sam .yui-toolbar-container .yui-color-button-disabled,.yui-skin-sam .yui-toolbar-container .yui-menu-button-disabled{border-color:#ccc;}.yui-skin-sam .yui-toolbar-container .yui-button .first-child{*left:0;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-fontname{width:135px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-heading{width:92px;}.yui-skin-sam .yui-toolbar-container .yui-button-hover{background:url(sprite.png) repeat-x 0 -1300px;border-color:#808080;}.yui-skin-sam .yui-toolbar-container .yui-button-selected{background:url(sprite.png) repeat-x 0 -1700px;border-color:#808080;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-nogrouplabels h3{display:none;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-nogrouplabels .yui-toolbar-group{margin-top:.75em;}.yui-skin-sam .yui-toolbar-container .yui-push-button span.yui-toolbar-icon,.yui-skin-sam .yui-toolbar-container .yui-color-button span.yui-toolbar-icon,.yui-skin-sam .yui-toolbar-container .yui-menu-button span.yui-toolbar-icon{display:block;position:absolute;top:2px;height:18px;width:18px;overflow:hidden;background:url(editor-sprite.gif) no-repeat 30px 30px;}.yui-skin-sam .yui-toolbar-container .yui-button-selected span.yui-toolbar-icon,.yui-skin-sam .yui-toolbar-container .yui-button-hover span.yui-toolbar-icon{background-image:url(editor-sprite-active.gif);}.yui-skin-sam .yui-toolbar-container .visible .yuimenuitemlabel{cursor:pointer;color:#000;*position:relative;}.yui-skin-sam .yui-toolbar-container .yui-button-menu{background-color:#fff;}.yui-skin-sam .yui-toolbar-container .yui-button-menu .yui-menu-body-scrolled{position:relative;}.yui-skin-sam div.yuimenu li.selected{background-color:#B3D4FF;}.yui-skin-sam div.yuimenu li.selected a.selected{color:#000;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-bold span.yui-toolbar-icon{background-position:0 0;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-strikethrough span.yui-toolbar-icon{background-position:0 -108px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-italic span.yui-toolbar-icon{background-position:0 -36px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-undo span.yui-toolbar-icon{background-position:0 -1326px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-redo span.yui-toolbar-icon{background-position:0 -1355px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-underline span.yui-toolbar-icon{background-position:0 -72px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-subscript span.yui-toolbar-icon{background-position:0 -180px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-superscript span.yui-toolbar-icon{background-position:0 -144px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-forecolor span.yui-toolbar-icon{background-position:0 -216px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-backcolor span.yui-toolbar-icon{background-position:0 -288px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifyleft span.yui-toolbar-icon{background-position:0 -324px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifycenter span.yui-toolbar-icon{background-position:0 -360px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifyright span.yui-toolbar-icon{background-position:0 -396px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifyfull span.yui-toolbar-icon{background-position:0 -432px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-indent span.yui-toolbar-icon{background-position:0 -720px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-outdent span.yui-toolbar-icon{background-position:0 -684px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-createlink span.yui-toolbar-icon{background-position:0 -792px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-insertimage span.yui-toolbar-icon{background-position:1px -756px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-left span.yui-toolbar-icon{background-position:0 -972px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-right span.yui-toolbar-icon{background-position:0 -936px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-inline span.yui-toolbar-icon{background-position:0 -900px;left:5px;} +.yui-skin-sam .yui-toolbar-container .yui-toolbar-block span.yui-toolbar-icon{background-position:0 -864px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-bordercolor span.yui-toolbar-icon{background-position:0 -252px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-removeformat span.yui-toolbar-icon{background-position:0 -1080px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-hiddenelements span.yui-toolbar-icon{background-position:0 -1044px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-insertunorderedlist span.yui-toolbar-icon{background-position:0 -468px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-insertorderedlist span.yui-toolbar-icon{background-position:0 -504px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton .first-child{width:35px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton .first-child a{padding-left:2px;text-align:left;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton span.yui-toolbar-icon{display:none;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.up,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.down{right:2px;background:url(editor-sprite.gif) no-repeat 0 -1222px;overflow:hidden;height:6px;width:7px;min-height:0;padding:0;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.up{top:2px;background-position:0 -1222px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.down{bottom:2px;background-position:0 -1187px;}.yui-skin-sam .yui-toolbar-container select{height:22px;border:1px solid #808080;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-select .first-child a{padding-left:5px;text-align:left;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-select span.yui-toolbar-icon{background:url(editor-sprite.gif) no-repeat 0 -1144px;overflow:hidden;right:-2px;top:0;height:20px;}.yui-skin-sam .yui-editor-panel .yui-color-button-menu .bd{background-color:transparent;border:none;width:135px;}.yui-skin-sam .yui-color-button-menu .yui-toolbar-colors{border:1px solid #808080;}.yui-skin-sam .yui-editor-panel{padding:0;margin:0;border:none;background-color:transparent;overflow:visible;position:absolute;}.yui-skin-sam .yui-editor-panel .hd{margin:10px 0 0;padding:0;border:none;}.yui-skin-sam .yui-editor-panel .hd h3{color:#000;border:1px solid #808080;background:url(sprite.png) repeat-x 0 -200px;width:99%;position:relative;margin:0;padding:3px 0 0 0;font-size:93%;text-indent:5px;height:20px;}.yui-skin-sam .yui-editor-panel .bd{background-color:#F2F2F2;border-left:1px solid #808080;border-right:1px solid #808080;width:99%;margin:0;padding:0;overflow:visible;}.yui-skin-sam .yui-editor-panel ul{list-style-type:none;margin:0;padding:0;}.yui-skin-sam .yui-editor-panel ul li{margin:0;padding:0;}.yui-skin-sam .yui-editor-panel .yui-toolbar-container .yui-toolbar-subcont{padding:0;border:none;margin-top:.35em;}.yui-skin-sam .yui-editor-panel .yui-toolbar-bordersize,.yui-skin-sam .yui-editor-panel .yui-toolbar-bordertype{width:50px;}.yui-skin-sam .yui-editor-panel label{display:block;float:none;padding:4px 0;margin-bottom:7px;}.yui-skin-sam .yui-editor-panel label strong{font-weight:normal;font-size:93%;text-align:right;padding-top:2px;}.yui-skin-sam .yui-editor-panel label input{width:75%;}.yui-skin-sam .yui-editor-panel .createlink_target,.yui-skin-sam .yui-editor-panel .insertimage_target{width:auto;margin-right:5px;}.yui-skin-sam .yui-editor-panel .removeLink{width:98%;}.yui-skin-sam .yui-editor-panel label input.warning{background-color:#FFEE69;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group h3{color:#000;float:left;font-weight:normal;font-size:93%;margin:5px 0 0 0;padding:0 3px 0 0;text-align:right;}.yui-skin-sam .yui-editor-panel .height-width h3{margin:3px 0 0 10px;}.yui-skin-sam .yui-editor-panel .height-width{margin:3px 0 0 35px;*margin-left:14px;width:42%;*width:44%;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-border{width:190px;}.yui-skin-sam .yui-editor-panel .no-button .yui-toolbar-group-border{width:210px;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-padding{width:203px;_width:198px;}.yui-skin-sam .yui-editor-panel .no-button .yui-toolbar-group-padding{width:172px;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-padding h3{margin-left:25px;*margin-left:12px;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-textflow{width:182px;}.yui-skin-sam .yui-editor-panel .hd{background:none;}.yui-skin-sam .yui-editor-panel .ft{background-color:#F2F2F2;border:1px solid #808080;border-top:none;padding:0;margin:0 0 2px 0;}.yui-skin-sam .yui-editor-panel .hd span.close{background:url(sprite.png) no-repeat 0 -300px;cursor:pointer;display:block;height:16px;overflow:hidden;position:absolute;right:5px;text-indent:500px;top:2px;width:26px;}.yui-skin-sam .yui-editor-panel .ft span.tip{background-color:#EDF5FF;border-top:1px solid #808080;font-size:85%;}.yui-skin-sam .yui-editor-panel .ft span.tip strong{display:block;float:left;margin:0 2px 8px 0;}.yui-skin-sam .yui-editor-panel .ft span.tip span.icon{background:url(editor-sprite.gif) no-repeat 0 -1260px;display:block;height:20px;left:2px;position:absolute;top:8px;width:20px;}.yui-skin-sam .yui-editor-panel .ft span.tip span.icon-info{background-position:2px -1260px;}.yui-skin-sam .yui-editor-panel .ft span.tip span.icon-warn{background-position:2px -1296px;}.yui-skin-sam .yui-editor-panel .hd span.knob{position:absolute;height:10px;width:28px;top:-10px;left:25px;text-indent:9999px;overflow:hidden;background:url(editor-knob.gif) no-repeat 0 0;}.yui-skin-sam .yui-editor-panel .yui-toolbar-container{float:left;width:100%;background-image:none;border:none;}.yui-skin-sam .yui-editor-panel .yui-toolbar-container .bd{background-color:#fff;}.yui-editor-blankimage{background-image:url(blankimage.png);}.yui-skin-sam .yui-editor-container .yui-resize-handle-br{height:11px;width:11px;background-position:-20px -60px;background-color:transparent;} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/header_background.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/header_background.png new file mode 100644 index 0000000000000000000000000000000000000000..3ef7909d3ed04956a06c5d9017076ea30e0ced27 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^j6kf+!2~3434ebKq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6*+jiIEGZ*s_F9NI$*%V9Q*UX`TlF!Ldi}q7dA02yr`^X zu-PrN{%75tzwegsKk4J*;_R|w)xBe%IT`Nt9oJ`MW0-m*yz~E_s%D^B44$rjF6*2U FngH9xIDh~E literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/hue_bg.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/hue_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..d9bcdeb5c49910d5c32c9ebbb134200bf138b7b4 GIT binary patch literal 1120 zcmWkuZA?>V6h6*nD|EKy_G>T#efd;-TcIEZRG=3KG$^eF2Q{FAMV4*KY}f{qh`QSV zerz}DmTbC_Y|fEr#w0P0=t#CW_qsTZ+oCcxM!nmzgkYx0y)F9Qv+IxZJb6w|&dGC5 zaz;Z<^@~z7QUPF5prJObvq_J$hJ`xXo5wcl^n8zhtsmg}%|C)|K3%8x)wT6C_ipWb zw=>oa{%CJkw=1x%v!^@U-5DL&ajAP1z;mggH7#{nz-rJ$faL=7qA45La$rShQh@N! zu%sTCvXE1t{K=eCf%*<$g}~m_lTbYf%#DuhOcn)}oyL+UY!^T)N0SIlg&q}p70^Bg z#v`A*ftBD@6%H#L*N*0!pas#aR&fdVH33r!@M?%V4H}RB^=Q5i+Cy}fVbYD}B4EjH z?P{0x>Acg883%Oa|AzJ?B#N%FVmw`fKNY;g=C3&BXB;Z@Kam~dpydSE;!)KoPs+}MGZ#35TL&dgu1t8ZJCOzunMR5)=3wB`6<04>Wd>fEGNt=fUO7S z2UdorB;0d<%}W2%DB8|}rj&7Bd@G600GiIAl}DfA(T~fGjEtPSpMM-+!RdW!t0gq&tGw>1(Ck!bL+QCwfHM zFSfg6C%J1(_sXrL%2?h=Gs#tB`jY5~^n-B4=5yiEV7#4=o|0Az*Nu@}Ih_Oz$pHOG zC`&0{EO(L#V`PcEmKepS-spt1Gd{>irzEF%o|nyJB4uhF{YR*@P1evnVor$^%6<|| znF`WIVUCMc(=ZuIiR8<#kjLU}uWTnbQf7F06KORJtfO9XHgzgQe;2kI(+lL6NRM$K zObK})t}2X5(vY~u9{XN8DGugG$E0mSB^Mi(>V!GlYlD8E#--~|}G|8JkdYdiH90fD-v+HZu-d;bSJ8}W_+ literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/imagecropper.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/imagecropper.css new file mode 100644 index 0000000..87a081a --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/imagecropper.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-crop{position:relative;}.yui-crop .yui-crop-mask{position:absolute;top:0;left:0;height:100%;width:100%;}.yui-crop .yui-resize{position:absolute;top:10px;left:10px;border:0;}.yui-crop .yui-crop-resize-mask{position:absolute;top:0;left:0;height:100%;width:100%;background-position:-10px -10px;overflow:hidden;}.yui-skin-sam .yui-crop .yui-crop-mask{background-color:#000;opacity:.5;filter:alpha(opacity=50);}.yui-skin-sam .yui-crop .yui-resize{border:1px dashed #fff;} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout.css new file mode 100644 index 0000000..de790e9 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-layout-loading{visibility:hidden;}body.yui-layout{overflow:hidden;position:relative;padding:0;margin:0;}.yui-layout-doc{position:relative;overflow:hidden;padding:0;margin:0;}.yui-layout-unit{height:50px;width:50px;padding:0;margin:0;float:none;z-index:0;}.yui-layout-unit-top{position:absolute;top:0;left:0;width:100%;}.yui-layout-unit-left{position:absolute;top:0;left:0;}.yui-layout-unit-right{position:absolute;top:0;right:0;}.yui-layout-unit-bottom{position:absolute;bottom:0;left:0;width:100%;}.yui-layout-unit-center{position:absolute;top:0;left:0;width:100%;}.yui-layout div.yui-layout-hd{position:absolute;top:0;left:0;zoom:1;width:100%;}.yui-layout div.yui-layout-bd{position:absolute;top:0;left:0;zoom:1;width:100%;}.yui-layout .yui-layout-noscroll div.yui-layout-bd{overflow:hidden;}.yui-layout .yui-layout-scroll div.yui-layout-bd{overflow:auto;}.yui-layout div.yui-layout-ft{position:absolute;bottom:0;left:0;width:100%;zoom:1;}.yui-layout .yui-layout-unit div.yui-layout-hd h2{text-align:left;}.yui-layout .yui-layout-unit div.yui-layout-hd .collapse{cursor:pointer;height:13px;position:absolute;right:2px;top:2px;width:17px;font-size:0;}.yui-layout .yui-layout-unit div.yui-layout-hd .close{cursor:pointer;height:13px;position:absolute;right:2px;top:2px;width:17px;font-size:0;}.yui-layout .yui-layout-unit div.yui-layout-hd .collapse-close{right:25px;}.yui-layout .yui-layout-clip{position:absolute;height:20px;background-color:#c0c0c0;display:none;}.yui-layout .yui-layout-clip .collapse{cursor:pointer;height:13px;position:absolute;right:2px;top:2px;width:17px;font-size:0;}.yui-layout .yui-layout-wrap{height:100%;width:100%;position:absolute;left:0;}.yui-skin-sam .yui-layout .yui-resize-proxy{border:none;font-size:0;margin:0;padding:0;}.yui-skin-sam .yui-layout .yui-resize-resizing .yui-resize-handle{display:none;zoom:1;}.yui-skin-sam .yui-layout .yui-resize-proxy div{position:absolute;border:1px solid #808080;background-color:#EDF5FF;}.yui-skin-sam .yui-layout .yui-resize .yui-resize-handle-active{zoom:1;}.yui-skin-sam .yui-layout .yui-resize-proxy .yui-layout-handle-l{width:5px;height:100%;top:0;left:0;zoom:1;}.yui-skin-sam .yui-layout .yui-resize-proxy .yui-layout-handle-r{width:5px;top:0;right:0;height:100%;position:absolute;zoom:1;}.yui-skin-sam .yui-layout .yui-resize-proxy .yui-layout-handle-b{width:100%;bottom:0;left:0;height:5px;}.yui-skin-sam .yui-layout .yui-resize-proxy .yui-layout-handle-t{width:100%;top:0;left:0;height:5px;}.yui-skin-sam .yui-layout .yui-layout-unit-left div.yui-layout-hd .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -160px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-clip-left .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -140px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-unit-right div.yui-layout-hd .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -200px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-clip-right .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -120px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-unit-top div.yui-layout-hd .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -220px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-clip-top .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -240px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-unit-bottom div.yui-layout-hd .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -260px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-clip-bottom .collapse{background:transparent url(layout_sprite.png) no-repeat -20px -180px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-hd .close{background:transparent url(layout_sprite.png) no-repeat -20px -100px;border:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-hd{background:url(sprite.png) repeat-x 0 -1400px;border:1px solid #808080;}.yui-skin-sam .yui-layout{background-color:#EDF5FF;}.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-hd h2{font-weight:bold;color:#fff;padding:3px;margin:0;}.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd{border:1px solid #808080;border-bottom:none;border-top:none;*border-bottom-width:0;*border-top-width:0;background-color:#f2f2f2;text-align:left;}.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd-noft{border-bottom:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd-nohd{border-top:1px solid #808080;}.yui-skin-sam .yui-layout .yui-layout-clip{position:absolute;height:20px;background-color:#EDF5FF;display:none;border:1px solid #808080;}.yui-skin-sam .yui-layout div.yui-layout-ft{border:1px solid #808080;border-top:none;*border-top-width:0;background-color:#f2f2f2;}.yui-skin-sam .yui-layout-unit .yui-resize-handle{background-color:transparent;zoom:1;}.yui-skin-sam .yui-layout-unit .yui-resize-handle-r{right:0;top:0;background-image:none;zoom:1;}.yui-skin-sam .yui-layout-unit .yui-resize-handle-l{left:0;top:0;background-image:none;zoom:1;}.yui-skin-sam .yui-layout-unit .yui-resize-handle-b{right:0;bottom:0;background-image:none;}.yui-skin-sam .yui-layout-unit .yui-resize-handle-t{right:0;top:0;background-image:none;}.yui-skin-sam .yui-layout-unit .yui-resize-handle-r .yui-layout-resize-knob,.yui-skin-sam .yui-layout-unit .yui-resize-handle-l .yui-layout-resize-knob{position:absolute;height:16px;width:6px;top:45%;left:0;display:block;background:transparent url(layout_sprite.png) no-repeat 0 -5px;}.yui-skin-sam .yui-layout-unit .yui-resize-handle-t .yui-layout-resize-knob,.yui-skin-sam .yui-layout-unit .yui-resize-handle-b .yui-layout-resize-knob{position:absolute;height:6px;width:16px;left:45%;background:transparent url(layout_sprite.png) no-repeat -20px 0;zoom:1;} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout_sprite.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout_sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..d6fce3c7a5bec2e266531e2b921f6a3bc3572bcb GIT binary patch literal 1409 zcmV-{1%CR8P)Foc7fVkN9ZLH|iPzfUuN*G~E00Ia|@iPD+ScV@e5BCj%&595~Az9JYb1HE%fJ|lvg&G4W z6xqeu5wao}vOGw#oOoq zdC>F%1Q0?EEY*Rd3zq4SGax3LA2VLCrA$0(SkZGRe)Txn3^>fhp`Mk2G^wZ|DoEi^P%kHvUUm}of|3c`UUt&-f|52O4U_0*PV)UriM_~rMM%_(97pUF zgq4T@9=!koXf2}^3PBhQEBt~NN?sh$J8ydbXFQt)$8tiP<$_ov{Q4FXyL>Z8Y{z2V zkaSb@Mp@4L)cu~!F2?_5njt5??aV6VWbNsf=#lQ+PR7RWs~T&qO?1)0;8OP9mr&?_ zEd!{i70@B06_L@4$jDGFl7UgQB&=k~SS7Maj>slCBAcYPu^a+2hmVBJ&?9G-+}TBz zXWWq~l#nFk3zof330q|P#FdpMx?{=@e9y*0nRuG?)9dbIA?=7Zn<-7Ogy z%rLzw;Z+H4qs~_O26Js?Gu0GVXL}YV+@i`mTQ6efT|4_N8}^c}3;8Lx-qSp(>c5yP zv+!2uj`O5iUE1Gh?d8?|Hp~2qjUgL*#Kz|yu(3mIobhzo0%%W3w;50B)}I;aHsc}P zSeq@=3AQYoV9T-zwk(^Ikvv-Un*@E(FC%n|1lUfINU{yq26f#+*Q{GQ%4Xe0YxQpu zv2_#y8&Nz-w%~RHx=DSu0s3URv(}ru4{F`oY^bw)ANJd!RX0b`Dd=_+pdGVqaS#TA zaC#8o%*J|#2HI+&(EtA%Z`Y=G+9q~V=ogzs#Fs&WPiD*-y?Scqb$UUo8r5tsP!;V9 z+So;%!C1xB@h9l0TBW5A>O>nFRjUhLtI#SPHmr5mvtO=H#t?b%!g$d!L~pK&n|i}L z!&%^r^XATaJ(Q)5hg3QzAHz@KF_|6%p4ElhboHes%dnJo?C(gon^x1UVMu9>l+$EM zyYYBITTA&JYj=J;UeH!t2igzSu&1+}ENH*(>w~#T?}~D>R>)!8tQB$?H*0yv+zy3X zp5FpK#BWTE@nL>rYK#x`TfkSiVcaHeL%A7)bE^@*P25(v!8sWU;bx5QQEo#=#9l_Y z9jWsb&xxPHEyHgiDKT#F_ig65r+y1bS-53z`*yvmBxe`^)OW4foqs1^G=pWW+-Vx8O~1UE+HGF@F06NmG=W!zJbw P00000NkvXXu0mjf;Dg73 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/loading.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..0bbf3bc0c0e5e635553e8d1bf9ceddefbc402396 GIT binary patch literal 2673 zcmchY_gj;P7RTSb83YJ1>=8y5ONL=ZcEgk+C?FydumNNz8c=c6`n&|fmMu_HHG%^w zNLVjHyfy)hAgHK_Kxkz+0Ktm5M|X*?y?g!o_3yv`{_^F^wY9YuFJ3GxEUd1s-nnz<)vH(c?%i8n zUVirM+2rIT007UQKY#e};oRKZty{MqJa}MhYina;bNBAu-+udTYHDhBcJ|n@WA*j* z-+lL;iHS*OX6D|#dm|zu!o$ON?b=mbT)bh!26uP&kdP1u2Zx!N8486$B9X?&$DclZ zdgI28>FMdk#l`#g@Bj4EPc=0)2M!!4EG!%z9?s6rzI5r**|TSdhK8)HtXf)HHgDc+ zZEek9Fk)k4xm@nHZQC3j9o^jACMG6~jg9m3^EYnX2*Yq^XJ>6~?X_#y4jnqQbLUQp zM6z$+zMp^o*}}p?p-?n8H=jOzx~Zv&N~Km+RkgLX9X@>c=FOXxm6dsUd1NvZ zX=yul?BMZua=F~p)O7py?EwJ+w{PD*dGh2hzx?v((WCP6au$mb!vmnqSpF6-9Ona(JQT#e>!KODwxYzG5#S|?M#v6eD#mgO^`=~9EL;yL&>*dd5*+XG=_`^3=CG25PbLa+LJ%N(PW_s z=_-TaM{SB!w(n7k+dMDN2G6VPqUA$u7F4m@ABAZ1D`*UMfe}E6csJU}J1Trmp#~7hZ5QSGpNvd1Uz$!Rf3q28pgSj9o zx?zwoWa8GYK@TOz^)mp#V2_VR5WfJ0W9BSSbn+cKb z7B9l9)K#s!?PSt;g%c8u;y7rd?hkP%>vq5BY=N>c=98V=+T&RSPgSu|E(FAK>B?vNN1 zPszwcbxJ?Oh|1pGd!9?gxzSWOR8o=x5!rGh+6r3hBL-14aTaAQxvJ|Y-S_m4niV2S zK@?}-9Dkhg<+w{Ny!vjyp-QmjyGmIW1DFB{k>P2=8cm~9M^_P#8?JFDumGEPaqJvf zZ{f;B#CG;H7q8a_hQ$pR6%%6So8vKM+W+cNPE_TI46^dn9q@qBr@1bUgxcPGB*b-i z3Hx_0(Esy5KKx^Y0yfgB6~}t>@!ctk>J|!vgVRhE2CPQ;AOKY2y%5nM@YF^ZMS~q}%L-n>Lpor#4w48UHYViOt={{43LMRvkIp+rkbs*s; z14}4q0y6`s8DL?uo-~*R@5tnFsC1DR#BGxT8fA20u_o?`0iDNI6lf;^$@AkR1dPTz z>XF1ZAqNjU95c@Vn59Wo;Z6b(YG+L$xy3(?j2I*vQ>PmzMEdh`yw3=)E}JYMDG|*x mDkGVJ;D)fXhxDI?kcM(ish)C#5QQ<|d}62BjvZR2H60wE-$(3-AeXt*@{D|Np;u@pDC#5QQ<|d}62BjvZR2H60wE-$(3-AeX1=9cj|6h7@{#_u8sU*lR z_&>wb?FL>zp1h}vV@SoVq=W_rH;IG.bd>ul:after{content:".";display:block;clear:both;visibility:hidden;height:0;line-height:0;}.yuimenubaritem{float:left;}.yuimenubaritemlabel,.yuimenuitemlabel{display:block;}.yuimenuitemlabel .helptext{font-style:normal;display:block;margin:-1em 0 0 10em;}.yui-menu-shadow{position:absolute;visibility:hidden;z-index:-1;}.yui-menu-shadow-visible{top:2px;right:-3px;left:-3px;bottom:-3px;visibility:visible;}.hide-scrollbars *{overflow:hidden;}.hide-scrollbars select{display:none;}.yuimenu.show-scrollbars,.yuimenubar.show-scrollbars{overflow:visible;}.yuimenu.hide-scrollbars .yui-menu-shadow,.yuimenubar.hide-scrollbars .yui-menu-shadow{overflow:hidden;}.yuimenu.show-scrollbars .yui-menu-shadow,.yuimenubar.show-scrollbars .yui-menu-shadow{overflow:auto;}.yui-overlay.yui-force-redraw{margin-bottom:1px;}.yui-skin-sam .yuimenubar{font-size:93%;line-height:2;*line-height:1.9;border:solid 1px #808080;background:url(sprite.png) repeat-x 0 0;}.yui-skin-sam .yuimenubarnav .yuimenubaritem{border-right:solid 1px #ccc;}.yui-skin-sam .yuimenubaritemlabel{padding:0 10px;color:#000;text-decoration:none;cursor:default;border-style:solid;border-color:#808080;border-width:1px 0;*position:relative;margin:-1px 0;}.yui-skin-sam .yuimenubaritemlabel:visited{color:#000;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel{padding-right:20px;*display:inline-block;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu{background:url(menubaritem_submenuindicator.png) right center no-repeat;}.yui-skin-sam .yuimenubaritem-selected{background:url(sprite.png) repeat-x 0 -1700px;}.yui-skin-sam .yuimenubaritemlabel-selected{border-color:#7D98B8;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-selected{border-left-width:1px;margin-left:-1px;*left:-1px;}.yui-skin-sam .yuimenubaritemlabel-disabled,.yui-skin-sam .yuimenubaritemlabel-disabled:visited{cursor:default;color:#A6A6A6;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu-disabled{background-image:url(menubaritem_submenuindicator_disabled.png);}.yui-skin-sam .yuimenu{font-size:93%;line-height:1.5;*line-height:1.45;}.yui-skin-sam .yuimenubar .yuimenu,.yui-skin-sam .yuimenu .yuimenu{font-size:100%;}.yui-skin-sam .yuimenu .bd{*zoom:1;_zoom:normal;border:solid 1px #808080;background-color:#fff;}.yui-skin-sam .yuimenu .yuimenu .bd{*zoom:normal;}.yui-skin-sam .yuimenu ul{padding:3px 0;border-width:1px 0 0 0;border-color:#ccc;border-style:solid;}.yui-skin-sam .yuimenu ul.first-of-type{border-width:0;}.yui-skin-sam .yuimenu h6{font-weight:bold;border-style:solid;border-color:#ccc;border-width:1px 0 0 0;color:#a4a4a4;padding:3px 10px 0 10px;}.yui-skin-sam .yuimenu ul.hastitle,.yui-skin-sam .yuimenu h6.first-of-type{border-width:0;}.yui-skin-sam .yuimenu .yui-menu-body-scrolled{border-color:#ccc #808080;overflow:hidden;}.yui-skin-sam .yuimenu .topscrollbar,.yui-skin-sam .yuimenu .bottomscrollbar{height:16px;border:solid 1px #808080;background:#fff url(sprite.png) no-repeat 0 0;}.yui-skin-sam .yuimenu .topscrollbar{border-bottom-width:0;background-position:center -950px;}.yui-skin-sam .yuimenu .topscrollbar_disabled{background-position:center -975px;}.yui-skin-sam .yuimenu .bottomscrollbar{border-top-width:0;background-position:center -850px;}.yui-skin-sam .yuimenu .bottomscrollbar_disabled{background-position:center -875px;}.yui-skin-sam .yuimenuitem{_border-bottom:solid 1px #fff;}.yui-skin-sam .yuimenuitemlabel{padding:0 20px;color:#000;text-decoration:none;cursor:default;}.yui-skin-sam .yuimenuitemlabel:visited{color:#000;}.yui-skin-sam .yuimenuitemlabel .helptext{margin-top:-1.5em;*margin-top:-1.45em;}.yui-skin-sam .yuimenuitem-hassubmenu{background-image:url(menuitem_submenuindicator.png);background-position:right center;background-repeat:no-repeat;}.yui-skin-sam .yuimenuitem-checked{background-image:url(menuitem_checkbox.png);background-position:left center;background-repeat:no-repeat;}.yui-skin-sam .yui-menu-shadow-visible{background-color:#000;opacity:.12;filter:alpha(opacity=12);}.yui-skin-sam .yuimenuitem-selected{background-color:#B3D4FF;}.yui-skin-sam .yuimenuitemlabel-disabled,.yui-skin-sam .yuimenuitemlabel-disabled:visited{cursor:default;color:#A6A6A6;}.yui-skin-sam .yuimenuitem-hassubmenu-disabled{background-image:url(menuitem_submenuindicator_disabled.png);}.yui-skin-sam .yuimenuitem-checked-disabled{background-image:url(menuitem_checkbox_disabled.png);} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator.png new file mode 100644 index 0000000000000000000000000000000000000000..030941c9cffc064276813d7eaab03d8c667ed700 GIT binary patch literal 3618 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 oFfyX>85y7$4gdfE0RR6300puDFk literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator_disabled.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..6c1612230550ef09678a38a2e3374585055a07eb GIT binary patch literal 3618 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 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator_disabled.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..427d60a38af14ac7b530a266dc2e969555d287c7 GIT binary patch literal 3617 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 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/paginator.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/paginator.css new file mode 100644 index 0000000..57a10bc --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/paginator.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-skin-sam .yui-pg-container{display:block;margin:6px 0;white-space:nowrap}.yui-skin-sam .yui-pg-first,.yui-skin-sam .yui-pg-previous,.yui-skin-sam .yui-pg-next,.yui-skin-sam .yui-pg-last,.yui-skin-sam .yui-pg-current,.yui-skin-sam .yui-pg-pages,.yui-skin-sam .yui-pg-page{display:inline-block;font-family:arial,helvetica,clean,sans-serif;padding:3px 6px;zoom:1}.yui-skin-sam .yui-pg-pages{padding:0}.yui-skin-sam .yui-pg-current{padding:3px 0}.yui-skin-sam a.yui-pg-first:link,.yui-skin-sam a.yui-pg-first:visited,.yui-skin-sam a.yui-pg-first:active,.yui-skin-sam a.yui-pg-first:hover,.yui-skin-sam a.yui-pg-previous:link,.yui-skin-sam a.yui-pg-previous:visited,.yui-skin-sam a.yui-pg-previous:active,.yui-skin-sam a.yui-pg-previous:hover,.yui-skin-sam a.yui-pg-next:link,.yui-skin-sam a.yui-pg-next:visited,.yui-skin-sam a.yui-pg-next:active,.yui-skin-sam a.yui-pg-next:hover,.yui-skin-sam a.yui-pg-last:link,.yui-skin-sam a.yui-pg-last:visited,.yui-skin-sam a.yui-pg-last:active,.yui-skin-sam a.yui-pg-last:hover,.yui-skin-sam a.yui-pg-page:link,.yui-skin-sam a.yui-pg-page:visited,.yui-skin-sam a.yui-pg-page:active,.yui-skin-sam a.yui-pg-page:hover{color:#06c;text-decoration:underline;outline:0}.yui-skin-sam span.yui-pg-first,.yui-skin-sam span.yui-pg-previous,.yui-skin-sam span.yui-pg-next,.yui-skin-sam span.yui-pg-last{color:#a6a6a6}.yui-skin-sam .yui-pg-page{background-color:#fff;border:1px solid #cbcbcb;padding:2px 6px;text-decoration:none}.yui-skin-sam .yui-pg-current-page{background-color:transparent;border:0;font-weight:bold;padding:3px 6px}.yui-skin-sam .yui-pg-page{margin-left:1px;margin-right:1px}.yui-skin-sam .yui-pg-first,.yui-skin-sam .yui-pg-previous{padding-left:0}.yui-skin-sam .yui-pg-next,.yui-skin-sam .yui-pg-last{padding-right:0}.yui-skin-sam .yui-pg-current,.yui-skin-sam .yui-pg-rpp-options{margin-left:1em;margin-right:1em} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/picker_mask.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/picker_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..f8d91932b376af76ccfac030c12eb9fec7ee4c63 GIT binary patch literal 12174 zcmV;9FLBU`P)_6|b&%Dfjpyv}j54LBIXFZqhE-_t{2r7|?ya1%Cs>h{sswI&ir4|Fh z$jAgxe*E!Arq9Rc<1hC3+xpMn|Ni&&sREphKX2dqw+!rCg4fvHA{v>|sAOH9VUq1Wx=i{&V_yqRn;}h7QkI%<-7fW_4(VkZ}j!+ z*W3A4Q2+7AAN1S*{zm`&=RfJ^|M;1H`st@nDf0RFlp-IAiA&;HZ{w3b`^>wEDMb|H zcWo7$YKZ}V2ee&$PJPY#JEPa?S+a1^5~E@1g&W3xW#A&D$3t?w{=G7DSsA*r_4-%Y z`s|z_E&o@}NSYWQ_Q@Xg&3d|Ou zW&0J1V(Gn21@Ok$tl7ApUjkd|>Gf{~b_Mkc=*rd-*uVe&`%Pc}`s=SZK(DV?u$Q+4 zw*GP77{rl7z$bi8N=|4%dgnzQK{K@X9=v7^ctch^o|!a57b!8M)R5bd+^DZB*f)2h zXi(pP{pA7dU4m@DUcq}~?BDNws-MON*}ARvB9}^yYkUl^^T(x&iy;x&pXVP)oMH zG4>x1DYCNm`n+yi_f;$KX~32?&=bL&3KR!`?Ad)hXq&kbL*FF~DPi6Lgmfs6L(D+0 zND0vbo2}RNnI*FeDS>21aabAxyE61@^}W7lp{p^l|7WGkjF52;svSZcA8su7jAYiZ3LweO3*sn5! zSD>!n=?3mEUmKmhK6d%BxhCszn^Za-*h3D(8SY6kiNgaaXQX90(eY3K$c_zH0Bie! zBHJ2UyB-p(7Bef5YbLIag?2iM6)3&}lecGR>8-$C0bN;o1$K2uG_Y5@@20Q6ep|mt z*;#x0tH7=ryq?1awzczFEUg2jL1spUI~;shFFVJMWT3#Y2!p-uSjIu7V%f`fjs-Ap z^O>)I7X@&(g2WB97X@e*&x;21dj4(4t<5d)+aC4x2CzHGU+%zOzu(5F>;Cn4UV*tj zZ$V@8yjpp$fL&R8ZO0o+m)B>04HkLJJo2A^{CRu7ZvXb}emug@Fk>GfXvJPL@_-^q z01_^oksZ=)$m(QUUX;~R(;!CYEsBZDLoIZEb1~!wBOR^fg#bCy%lortW+6TF_FY@w z&6w46@B~bZ!ZnoFU!@$z>E}`k{^oUMnFB{O&3px81f^O z51QS()3a{J?CEH!+pUC&YHNa5>Eykw2XY`qJYY8f?~*Z#9Wbu!EB)#UYzgYy^IbES z3h4T`vT|kq^`Z574Oq_r_AIDJ0c{44L7>OU1PLbsz#Hu@vK`wj512a*;t0UHoeBa? zk6L-sMY|p{s1$`s7O*7~*BX(c{b~v9`g)Thw{{({Us@kq|5b2nV9S~lBm$l;MJBR- zSsN}46ctdtgi9+$xa(0`+j0;b5@@3(htB#Thl4>@u&CE;xE$KTV_CN$*;#_wksf7p zH>9;!8MRBwYyjM)2y#PKP>c6P+kZ7HSsw`0kDr;x8GBY&%c%cEP&e$K0;+W$c6Ga3 z-f4l|(a#9Tgjm>eL6n{@$mNioz>^;m>!~orEy~tWx3~ zOIPqpfCGkR(H?r%tE(Zjv@CMcj9p#<%|dfa05{ue+I>B?x*{YBs9Lr@sIdpzjet7C z(j3YXHqYbA7G>{gy$rQE(#f8iq4wzn3QC-$G_@y1j3806bjQvT*z2!Z!CPeq$}$Qt zKiFGHksaJG`+EfLE_ox5tq+;W^uV3*u}1^OjK^IhVL9wdjz0DhDyAkTJeq`!B#Pcg zhP)_7_7G+P^?uQ&deV!Q8k_%Iz3u(DO+Od8Pl9$mZo9rWlUfCjjYrK(<6~b$ZT0S1 zS3O;Ux%tu+)a&a-3?R6yAif2U*Sn8h->)oR%UIXfo6X1d@8#Re{rTQ*_p!In<@$MS zi0rd9cH9YgPHQJ6i50k+-%kgas7Aw(CeRhp9mnRTLOFML>EN7Z(g?zUW!g!Hg9HcE;V1EAh^ef|OhyG~Aswq6=s?q4)8Rd863y;SWj zSY7I8OIMc~2-fXFMwH5^wNOOZdAr8m>OGbX*q5qptG2GXdan<;-u3UQn|Fkfk?i04PcV*!JYNDjCSSa=A`)xBsyFVf!o zcEj3Z$<&e+vLHr0ak9iY3#aPde)nR zA-C1eupV=%_1K$crutm{Xra05zTK<7Zd!fooV!f@ zjN&Brbhe|X^)|DOW?&^TSXpb-J8|rPncYZ6g>MN)cr9$&910<@S`i zkQl{aQy;-2thth!_d8NT%MNOLaRo zCuFG|O0cz;&U9i--BvN-HZ`yK2WHwUjV^zvpBugv*x@U8x z({-K67HqPx8;i~;!e{od_khhIU{6k}7aYNF7KD;K_3|HlOG;X68|WyQts~R_Ey{93p$q#vLD)BBQJf!DrZ2nhQiG*TS=m|!i=sNPks~sAWNwo((+QeE z#&&JLOxr|mJq#Wvwe^U!h^q1|mxGNOYb!WJG9t^^ z7DMZKI!Lj#PN|b)?X9WqMFoppm0nG~SG!I#I0zVZ`DqtCYId&sD^t_0?Sst)+mcAN zUvx@c>}O&7-Gj-m-xe7Z%Keh9Wq_!IMZnTSjO}I%4>EJ4jWgw@5p#Q)LYiP`6fiQd z^$Ve27n-UX6~u~jBf+k#TtGMMS9dA;lIYZHi)4l30jO7QF&T(%QhouWT^ zynfVSX2S`ZnZPko&ykt#z}4MKa~F_k(OQ~~0%y}dDP!_F!}v#hlq(gM^>trIkoxdHpiniE-2)#zvMuOXYZ z@JTauPGdhoUrzx&2nsFzYz-P9uOq1X=#HU5Icmr1+m7`=TI)3+i)$@z)KfDUFrb|e zMgs?s-Dk1u&Z5gh$7`mpZ50a_t)I09Z_Y2;>j48bSd6fih|8uJJL^RwJv?I9MOj1S zdLU4vQqm5rNLt8_pn<5I7Sa+!IUbUAt>rFsNh$%|eUVd;2@Sq8wo0jAKq5vm`3kt3 z=3N~Rsk>_m9Wl3@TSRJXnS>Dm>Ye59TAeks*WX>pFw%@&JCaPu7;eaM#?H163Yxqm ziO1X{Y;1uY1)XquF~r!S{e#6HD+K5cU}@)0U+V%VRlwA-9$@K^y(J@8pB$}LpzaKz z#@63&zauQRhE`R26msV$Z^{OZT{Yqz~|MKp5@rfxL0c0%O-=ufe>>^uw{kcP3JqOoTg z+bjHcEIkgV+Xd`yFtrAF15DLXpaVjTJA-wc7@{Rz2CcE1z_Vdg<2a#%A@fTHRary$ zx^qPy{_{TkOX+1&?B6kR^}s#nLpfB<^+cJ+!)2=@cHV%N&a^i{jchr@!b(pU4J^^d zO17|ADFAxZ`eGm^1_e)qtT@Ery0EFfmaLv(=|+cN8%Rh$tyRdxLGaieqrB*@ zL#S!P*wWof-%8)Qb4e_g_L$k4z#SDq0S(+`G&PH>PTX|r+7{K~Ti3eID{{XsPtw=} z0bxo@dr1_)!UUvA#=f(B>9TP$k}MsN5fF`Yl1{Sda#ZD%T;wD_* zrR(uRL+ilL+JnOY9wm9-+$udbbEn?0(LOj>$r_hai=7gPtL*qQi|ZPXQR$29gp zkeHn=VZ^I8vx(Xr3C^*P2@HVj>StOa=0bwJ{*liQX>WaLOu?0&v$0Jsj zZGj8Z3^mjKv_3!Zt()Tzw)7pqx@$jMW2a1WYelRebzTA;ZOaH?FNSYztt>#^x{9&}1iB)CrBSv~c-4}XJO4VNu`kuHu8xMR`H+r@WMy3&f@(oD zV-IQUBfyT>ItFjOyTqV&0>y3{a4&QaiC7u|8A%bSB@^2+!6JcGyO0!VK!4kJZHk>1 znNk-3?ybKKaCMsmp|tx{qUMoqf7#pY9YA&lk%ZZwrPU|5J9327sG0NZzDc%Dr%025 zqCIwz@d$Rqv$k9j0=G{sMPM7F99180rOMfIOX{5lSZj~hBGDq+p)@>{DBd>D(nB2@ zz1GjEM9YEo=n!M0*-1Ij*Dw%_*w@JncJ0>&i~KC^eP`rF2U)|W{@J)VA!A!|1Qar* z*jjIw0i|Z_ef0$;GbCeMEUibRZ?mK78J{kaZ6ym=Hg~jl6AQ>=HEZjAwYpG94|(1j zW6N|q-Bz=DfN-cDdxU)xSwru&TsGqlj#fXTK+$96&LKfghSJ8J%i;Ld466Ic7^EwK zuHB7AWfjo^qGj`m7f~6w&sVL%jGPcDOR5_pYDq3q8i?$oc2L&4#06v<775i>3x}i}tq++VK{F93+C@%G zValBBMTkrmmI0*)W{`~}Bamck?hjo=AIT2H;zr=Ov-i5ctc-b|dO^D>y);olB4TMB zC|XiP28;VR$Cqm(8I)rp>kC5c^snH_B6o0E;XOGDq4mJAaYlw*nfA;o{!0X+V9n+`Q=20nuSDlk0 zdgAwJ=+@w{od%FmxoH4qYj6Ry<_6@487vZ>V-HCY_L4Ek;gHVAHhozyMcV2<0vW}W z{7{x50y!yd{Q&F2azst1q4hSTulr-+Tp`h%A*?MwAJ_+zEJ?ObOB4spn(@)R)X>2& zf=kQ!usm=ppk%N<3>mc_`qq7y4os*fgh3{fE%yV-ALNecQ9724spY3iR-n%;mLmd6 zE873Ja6=*qeEPg1Cyb7X=BtLlGg9Z#Gl5!Z*j^VXfzjv;q(@hx2?D~5Jdw7U_P2|X zXdzX>N67uq%&cTd!^|?#(m5pyv#$2jQbRr?MwiJL*{)@0>KMC94OKA3K#t72B8eGQ zho%5VV9w47VpMu*-A$wNL!A%GiU-iw7fW|M05Jh}mf1p5fbI&HM3Gac!nzy#;7ldzS7-AeZ2l+khNtzzZzBJg{dp zb~=mbyw7Y0_M9bK!fawT={_?Rk|qSC2C5A~wb;**BF6L!W`$oc0wS#Y$YvKE zd17j5OQIOlnsscaN0*DLL$AtD>*~b_1WCz@B5FbwppQe4OMr?AbDH21$qb#P1Oo$h z`Jrt*5Px-YLqh0lp~&%y-E2wy05*1A5Qnk%VHvfhCyH zC=hpY#SvhGb9KOVK)%&Y^RnGaB(p=7)*V4_v-Gn7YcXoCFRC_(RZ!S6b8Cfqwbxbv zIj6A?%91d9Xt1|+Of}XTw3;!B44<0% znWwtB|2&P4+P1NSp^2?K9QLkzeJ!ClT9SHNtqA8<27~p{mMh}O4{Na_#LV9CBRDWv z0#Jih47q~#9>@&J3tPNlQHDPawRfPgO~%%`y0s}74Z!7ym6a4BPiw1+ygEt-x+0)F zb#IHD5sR_Ifd)sVNL0&_vGT}Xc+?%csAYn*+Q^s#o56yZ9IR5MSuC&vo8!1&Bi#ab zqlFVvgjB+%|65pFi}1B2Pjo6A6*5T>N(ltKX>(B|m0NHnM|lj~Jr~#sRwic^FJ1-T`NnK`Sm1G_Iw#v}#|WQK-WlSrb8+AYnEC!}nrHzOofG;mq1M+5E# zF0gem)7`OLLSQ3s1BPWaokAx|WSl1)5O_Z6ba(|#QZlH~GNb{nI{^wDZ8k5vpDICX zWG18F@zH)Vr5-va5qopI{6+-mtjzF^x9ma0=x8jY25H&De=xXL-ukp$GA4EJ?nEl- zQ?{Ut(U?OkHjw~DK_d!wv%y_+E+_VTv|H%tHi!TN=lLhqd)(n^$wIw5XbX}6n z`wVcC!1m9<6ftn4w>5(+5MMNCf!6LiiE4Whw^Y6wQ<}v(+fAE42iREv2fEtS=E3Z# z5uh!P+mj_oiZsVqH6tECPhe|8cAs!~*a#jwEAVkGN;B?DgH?WY8pQ;Rv=0J-zk#a?d`U!O06|i&_pC0~% zs`H#tCai{-F-YNecP#Zgvjn-m4!WXHOEei+>hHL2yn0o89qjDD)2se_dhnP@n|qag zq7K&uG4;zpyE+``=ZwZifMAQ|GqM9DW;}m7&*Dql$%OnMBsqMELWGhrj(%q3(o|;F zm3fVvSr`q@)mGl(=b*|dsgt6oOp6bR~u`cPXan(Y?Gyewo|O!dC`^>(LOeEI&2wo%g8#w=7X*X=dws6C9Z=RM)P&R>XeWcW*}*S9|dBO z#E4vw6hn)0PQ$k*rB~U=N_Ki%gBgJqonHde7}bdbG3X-bM%8BGh!5%`glVkCChN}~g3BW$M}kFK2>ONsVtFvIPh8-j|! zP`X_o->~@7R1I1~_EP)g01;!(lkT_dq{zVuDO3BhOrBuw4xoebW0}oV0S%e1I!G@ zS(<=GAhvWhk}V>&+|*Y)b=L0-?9AW-BY4bAxj;rqE3At~Ky}WW0=SHa2iUo(K{h79 zoT?DC0FAa;NfwZ-@hm`!>^_u$QRi@h3rq?mNydOZGE=G{H&Tn{xCKvROl{R@LvI^( zB**_YItF)xh#kMXDH{M%hCO)$0MF=nR&EvuhTU2bMl1Q!wJQMKqreW=pfU8fHKC=;%8?Wy zW7a2QbPj5(!NIjz>u$oivp7#D1d0NoTZEjF9$;1MK(IMCCG zx#4mA491Rzkwx{-qhlU*CEw$JHpIZDM;^H+`-KBjpLq;>6vPe?U29I&lkB=&7dC0T zkL-zu_B9&G9&wIzIR`R>lTzb(!J|=U9R-`&X&KV;#bWceXp7Ay_biXxa!>Y)!Gw|^ zRzPXZRpL4+;23w5y4e9ilxJLLJ(vJZZMK~=hmp~M@T|Zw#n?zU2c03D=h^@)oM4jt zsnM*VVdlh?mfl95dUI}PN`okEK2kL0v3MjOvN9u+K?D|Fd;ZM@K@!6VE-4WpdRjVS z`e9&)&ImiJgbn!Hp)7H-n8gVs%>dH{es0F7IG{|}g8|!fpqD#of!gVkQq&1hX3_GZ z_3_C-5c<`Ii&6%I$Pr){sa-I;}6YGm*O`nF^QD6H`R=aiQ0s=u4 zTza2}Kqg;X`>lWu)lt7?a43FWI*YMWGq5^yjaX|lW+X^@MFS{LxLd9dEvFY2K>Mgp?OA;_w>u?86cFL0 zl^u|i`zRqxP>`3><7&bkb1pweD>LXk79h=KJ3K9)2o~)&cO%)=1g}F zezt&oXXmE4tL+eryM}%D`&caP0o?<5GC3n&x1^uY*oC}O)4&Ny&lDB0x4RvToOh&) zr$x!r&{le0YierKcvjGr`MhwQN2@c|(vL0gU66c2WH&Pd(};GS(b>6m9(kOx2U$5v z@|0jSjm6$YCkMz`nb*JIW&u`KPe-hr@wz*AM^1+0bSRGYKYlwV;Do^T4dXIFHa6J1 z)5oZS&(qlha)lDCehAo6iE0Y?R>0YuTY#ACrKQ=>*;xRyl>~C^y1g2X{k0@ro$W{? zwvM-s$pDz_i65J#OcG%Bz!;8vLC%YD?so%r2z*0VV~N1-I_u_z2H-X|cn0LCMglSM zk_53Mlgw>~!{KUf$8{>kWIt>;QEu|Y(%7QI@3#!A20N#nd+-LJ&->U1fju>|lm~u` zMVtiAa2v1VIPJr2mhANV{@gxO%YTY*rpumms_z`G6*Nz z@vOfDix06fV0>$B$utX(vNk(w-AuBv%gzxK2aX60xFRL6_ufZ}bZ!6>Cu>P8z_~%E zH<=FdoV||Vfm~{K063R%M}Vz=BS&@=XYTJbm>oS$PO`<-#+Jr*?hJ)Bt`PObM)kSZ8H|g?k<=*@;I^`DUND+wP){p6|2G-|G5*}WiV*^B=KId- z;G@Tf8k-jmEBQtPM31$T_1&(cVlBrp3fd&t$w|wntNq&V-IN5&It_E4@Imd|Kl?!< zfuUTc3zAHObCRvo`Z^&~rld%Ai4Mrxfz*f=J2kV1&iOMk#tIN2lVtAiQla>BXSp(9++bG|?7bP^y}FKW_JBeC3hEjw3ZfkQ=ooGj?Ibj8S#saVB*- z(a3wWYzYE&Mi#gdr2U=EcHfQNhXCmfHXuAzgA3lI-REUKqmoum9Ai$?F!CHEmD0~z zqF9XWl^>uxWn#1olpsOM+>$6(x}0oQrzmhdPl^o4kuac)((nmM5;-1}WlGssZT7om z&`$%t(;*_@Mk^abP-k3?V4{ACM!F=WN2VN=j44B&BSj(rM^iD32B1+VaO%L_i|*Y4 zY*t?&sLqff4*OA7!ZgPku1D6@utwCJ{WyPAO_H%kf$k=8h&W*C==PQYs~c!Wj2#U! zFn*)-F|TRRDm+6Dq3p;2+49V@!K-(?{xPPPoF1to z$x0H=yC}mJp~L3**vIz?8MOj$Qro8;i>#|LTTB(5kG`YF^a7^fmu>C|j@F))CsXdp z2*c0Hi~~%Z-PZrVI2D6HRvrQW5r+0;$An*<4jfMfb~Hxr6qu(0VIU{6XB%fdUt+7GKM$ZQ7d z+*G-q^3AhAkG6UGeKe43wk=Z~@{qi^8g4~a7kh3;^x0=fpYx@Ed05BU<|1?Y@y9GNH9cw6|*ydMtC~bu#Ur zW^%V9`U#e%tuqzfu>F?#-9|w@YT*rZk~0~*#cRn2ktxkSAW3Ed%?xnei<~%b>YUvy zQB0iuZb_Yd#{V~D+^D7_lR5mbj7|2~MWfx0!AN^YIy$^?2|Zp0fzVvE@~A_$*cnVA zMw#g)ypCq2vdiFXhx6E0)LqSNUxhI zVW-W=i}3ha-8{;~vjY#ZReptXbC!%U_7TS<<#h*49XcddFz8&+VQpzLHIvtFG}ukc ztmOZTJf~!aiH*rPc@pR;9nD7=JCGdVDq<116>`I1b5xT@tC-Dp5?2cO>`Zi$Oc?Cc z(=Nq~W}cBGvz~W!9>~};tnKM?az?r*E|O;jW_03+7UVQwICongNlHz~C-}PvCLZYw zR_qcowKa`$hP?y!^;8FkQe+UQgE~86O1M%&)(VWI%!rlfG4Y`wbreh^=ZP%0M8brg z;dU5oO-Jt}hg^{e*c8v~l#?WMUt?_~z?@+B^hF06nQ2~sj#!{Wam0bn8hwA4g(GPp zre)|l%aSOn8U*|Kj6IRW895IgvD0rHxqx+pbT_1PaWqhU>-R^eY8dPASqqQe_aWKy zbYM@gdG;KmUU;{SlVCmuzzWeg767aWXd_QWP{P+&9)h)*5Dlk z!wjP}|BcZa_lfvoG{C0G|7UodwcV@AJHfqqjue^oy9ceoY@nI}^Q?wH6;v~TLW`Kr zXy79tKO?#FmJgG$lhVOuZE*2ZjE(?$gwY2R3`cIyVJA+KNNfEK$gcDqZHkf0VMdOe zm>Iv^1hyK8I~oYO9l-Us@yB|M4gsFj<5}h%0zYagcd)ZD(q&^V&IE^>F~$_5al^!k4%1 zJn&9?;+~W-ewCt^;T`NeM?jwi+M(lXmEnk#nsGM*Cu2AujAFmD9g=3^cRpazg{)2P zn8^slCiA+?NR(!+NuZ1{S-MkuZF%6gv9{}!d*XLgzfH?4N!?6zAmK9F0seNx-8fs1 zXDviP*JZL(3;|+<;j`Pb3|s~}q7~H5vaL6j*f~=voG(jG12zp0Lhxjb*#NQD5r-zc z8>nBrJig*G4d%vKNVex5w1@9RM?K}U<_D?ky?<0-r@?(R`7p`ot`?H2s#>^rZ4^=FlN|z7;uANn-1>IN}N2Cr3Zk`BP^T*Bp+h=GXQ?n zq4@~xH~`i&0DT(!&VYJ`-9wFiKyS}TnG}0}0I747b%*zVRH^Xn>CK)NJe~mTrv#t_ zcabwXLIlFM0P-}L$AMa&#=dX$_}d`x3eTZ?RLY=?o8@$7*!k>srvp9PW)jSU?U;_9 z^Qe?K+IdESZGby%u+M1qd$#NeEItDAvw?m9$ftmLQX9{>7*l{gdPf)rHlFHin8at8 zf231nfja`;X`qjQ{TPtT2$-J+=#L;%GCuZM%zFe-GoTq|EqXG0J-rjFA!)YD@D%G+(%jVtWGl1QAU{d2%u&<<*Zbo86f4@e+txxnf@rS&tmU0L4FkI zvtVzu0H1hQIRnIJ0C_feJe#F6_kc5iO=q3M`0__VKFhGvjLYYO_Y5XJ1jJ{7c^Yep zHW&J!52nA`qtNH$?S3o4*oSLk&tTSPNrW?X?<5;9naK^$U}fVxx$Ap|$u2f@bg3gWkxHK%Fp4+8RMf$}i0&g=*$e&(C#qxaD0ZvpHl zv+I6`Mm!BUmxWOUFGBaUp^pXA9e5eL-vl3cNcl?@AS6vgTG5D@?CMq zTi=Sx2mN33JO2+a9~-FUJu&myl|RHap8Fr(82g7GfB2M~pO3%P.bd>ul:after{content:".";display:block;clear:both;visibility:hidden;height:0;line-height:0;}.yuimenubaritem{float:left;}.yuimenubaritemlabel,.yuimenuitemlabel{display:block;}.yuimenuitemlabel .helptext{font-style:normal;display:block;margin:-1em 0 0 10em;}.yui-menu-shadow{position:absolute;visibility:hidden;z-index:-1;}.yui-menu-shadow-visible{top:2px;right:-3px;left:-3px;bottom:-3px;visibility:visible;}.hide-scrollbars *{overflow:hidden;}.hide-scrollbars select{display:none;}.yuimenu.show-scrollbars,.yuimenubar.show-scrollbars{overflow:visible;}.yuimenu.hide-scrollbars .yui-menu-shadow,.yuimenubar.hide-scrollbars .yui-menu-shadow{overflow:hidden;}.yuimenu.show-scrollbars .yui-menu-shadow,.yuimenubar.show-scrollbars .yui-menu-shadow{overflow:auto;}.yui-overlay.yui-force-redraw{margin-bottom:1px;}.yui-skin-sam .yuimenubar{font-size:93%;line-height:2;*line-height:1.9;border:solid 1px #808080;background:url(sprite.png) repeat-x 0 0;}.yui-skin-sam .yuimenubarnav .yuimenubaritem{border-right:solid 1px #ccc;}.yui-skin-sam .yuimenubaritemlabel{padding:0 10px;color:#000;text-decoration:none;cursor:default;border-style:solid;border-color:#808080;border-width:1px 0;*position:relative;margin:-1px 0;}.yui-skin-sam .yuimenubaritemlabel:visited{color:#000;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel{padding-right:20px;*display:inline-block;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu{background:url(menubaritem_submenuindicator.png) right center no-repeat;}.yui-skin-sam .yuimenubaritem-selected{background:url(sprite.png) repeat-x 0 -1700px;}.yui-skin-sam .yuimenubaritemlabel-selected{border-color:#7D98B8;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-selected{border-left-width:1px;margin-left:-1px;*left:-1px;}.yui-skin-sam .yuimenubaritemlabel-disabled,.yui-skin-sam .yuimenubaritemlabel-disabled:visited{cursor:default;color:#A6A6A6;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu-disabled{background-image:url(menubaritem_submenuindicator_disabled.png);}.yui-skin-sam .yuimenu{font-size:93%;line-height:1.5;*line-height:1.45;}.yui-skin-sam .yuimenubar .yuimenu,.yui-skin-sam .yuimenu .yuimenu{font-size:100%;}.yui-skin-sam .yuimenu .bd{*zoom:1;_zoom:normal;border:solid 1px #808080;background-color:#fff;}.yui-skin-sam .yuimenu .yuimenu .bd{*zoom:normal;}.yui-skin-sam .yuimenu ul{padding:3px 0;border-width:1px 0 0 0;border-color:#ccc;border-style:solid;}.yui-skin-sam .yuimenu ul.first-of-type{border-width:0;}.yui-skin-sam .yuimenu h6{font-weight:bold;border-style:solid;border-color:#ccc;border-width:1px 0 0 0;color:#a4a4a4;padding:3px 10px 0 10px;}.yui-skin-sam .yuimenu ul.hastitle,.yui-skin-sam .yuimenu h6.first-of-type{border-width:0;}.yui-skin-sam .yuimenu .yui-menu-body-scrolled{border-color:#ccc #808080;overflow:hidden;}.yui-skin-sam .yuimenu .topscrollbar,.yui-skin-sam .yuimenu .bottomscrollbar{height:16px;border:solid 1px #808080;background:#fff url(sprite.png) no-repeat 0 0;}.yui-skin-sam .yuimenu .topscrollbar{border-bottom-width:0;background-position:center -950px;}.yui-skin-sam .yuimenu .topscrollbar_disabled{background-position:center -975px;}.yui-skin-sam .yuimenu .bottomscrollbar{border-top-width:0;background-position:center -850px;}.yui-skin-sam .yuimenu .bottomscrollbar_disabled{background-position:center -875px;}.yui-skin-sam .yuimenuitem{_border-bottom:solid 1px #fff;}.yui-skin-sam .yuimenuitemlabel{padding:0 20px;color:#000;text-decoration:none;cursor:default;}.yui-skin-sam .yuimenuitemlabel:visited{color:#000;}.yui-skin-sam .yuimenuitemlabel .helptext{margin-top:-1.5em;*margin-top:-1.45em;}.yui-skin-sam .yuimenuitem-hassubmenu{background-image:url(menuitem_submenuindicator.png);background-position:right center;background-repeat:no-repeat;}.yui-skin-sam .yuimenuitem-checked{background-image:url(menuitem_checkbox.png);background-position:left center;background-repeat:no-repeat;}.yui-skin-sam .yui-menu-shadow-visible{background-color:#000;opacity:.12;filter:alpha(opacity=12);}.yui-skin-sam .yuimenuitem-selected{background-color:#B3D4FF;}.yui-skin-sam .yuimenuitemlabel-disabled,.yui-skin-sam .yuimenuitemlabel-disabled:visited{cursor:default;color:#A6A6A6;}.yui-skin-sam .yuimenuitem-hassubmenu-disabled{background-image:url(menuitem_submenuindicator_disabled.png);}.yui-skin-sam .yuimenuitem-checked-disabled{background-image:url(menuitem_checkbox_disabled.png);} +.yui-skin-sam .yui-pg-container{display:block;margin:6px 0;white-space:nowrap}.yui-skin-sam .yui-pg-first,.yui-skin-sam .yui-pg-previous,.yui-skin-sam .yui-pg-next,.yui-skin-sam .yui-pg-last,.yui-skin-sam .yui-pg-current,.yui-skin-sam .yui-pg-pages,.yui-skin-sam .yui-pg-page{display:inline-block;font-family:arial,helvetica,clean,sans-serif;padding:3px 6px;zoom:1}.yui-skin-sam .yui-pg-pages{padding:0}.yui-skin-sam .yui-pg-current{padding:3px 0}.yui-skin-sam a.yui-pg-first:link,.yui-skin-sam a.yui-pg-first:visited,.yui-skin-sam a.yui-pg-first:active,.yui-skin-sam a.yui-pg-first:hover,.yui-skin-sam a.yui-pg-previous:link,.yui-skin-sam a.yui-pg-previous:visited,.yui-skin-sam a.yui-pg-previous:active,.yui-skin-sam a.yui-pg-previous:hover,.yui-skin-sam a.yui-pg-next:link,.yui-skin-sam a.yui-pg-next:visited,.yui-skin-sam a.yui-pg-next:active,.yui-skin-sam a.yui-pg-next:hover,.yui-skin-sam a.yui-pg-last:link,.yui-skin-sam a.yui-pg-last:visited,.yui-skin-sam a.yui-pg-last:active,.yui-skin-sam a.yui-pg-last:hover,.yui-skin-sam a.yui-pg-page:link,.yui-skin-sam a.yui-pg-page:visited,.yui-skin-sam a.yui-pg-page:active,.yui-skin-sam a.yui-pg-page:hover{color:#06c;text-decoration:underline;outline:0}.yui-skin-sam span.yui-pg-first,.yui-skin-sam span.yui-pg-previous,.yui-skin-sam span.yui-pg-next,.yui-skin-sam span.yui-pg-last{color:#a6a6a6}.yui-skin-sam .yui-pg-page{background-color:#fff;border:1px solid #cbcbcb;padding:2px 6px;text-decoration:none}.yui-skin-sam .yui-pg-current-page{background-color:transparent;border:0;font-weight:bold;padding:3px 6px}.yui-skin-sam .yui-pg-page{margin-left:1px;margin-right:1px}.yui-skin-sam .yui-pg-first,.yui-skin-sam .yui-pg-previous{padding-left:0}.yui-skin-sam .yui-pg-next,.yui-skin-sam .yui-pg-last{padding-right:0}.yui-skin-sam .yui-pg-current,.yui-skin-sam .yui-pg-rpp-options{margin-left:1em;margin-right:1em} +.yui-skin-sam .yui-pv{background-color:#4a4a4a;font-family:arial;position:relative;width:99%;z-index:1000;margin-bottom:1em;overflow:hidden;}.yui-skin-sam .yui-pv .hd{background:url(header_background.png) repeat-x;min-height:30px;overflow:hidden;zoom:1;padding:2px 0;}.yui-skin-sam .yui-pv .hd h4{padding:8px 10px;margin:0;font:bold 14px arial;color:#fff;}.yui-skin-sam .yui-pv .hd a{background:#3f6bc3;font:bold 11px arial;color:#fff;padding:4px;margin:3px 10px 0 0;border:1px solid #3f567d;cursor:pointer;display:block;float:right;}.yui-skin-sam .yui-pv .hd span{display:none;}.yui-skin-sam .yui-pv .hd span.yui-pv-busy{height:18px;width:18px;background:url(wait.gif) no-repeat;overflow:hidden;display:block;float:right;margin:4px 10px 0 0;}.yui-skin-sam .yui-pv .hd:after,.yui-pv .bd:after,.yui-skin-sam .yui-pv-chartlegend dl:after{content:'.';visibility:hidden;clear:left;height:0;display:block;}.yui-skin-sam .yui-pv .bd{position:relative;zoom:1;overflow-x:auto;overflow-y:hidden;}.yui-skin-sam .yui-pv .yui-pv-table{padding:0 10px;margin:5px 0 10px 0;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-bd td{color:#eeee5c;font:12px arial;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd{background:#929292;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even{background:#58637a;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even td.yui-dt-desc{background:#384970;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd td.yui-dt-desc{background:#6F6E6E;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th{background-image:none;background:#2E2D2D;}.yui-skin-sam .yui-pv th.yui-dt-asc .yui-dt-liner{background:transparent url(asc.gif) no-repeat scroll right center;}.yui-skin-sam .yui-pv th.yui-dt-desc .yui-dt-liner{background:transparent url(desc.gif) no-repeat scroll right center;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th a{color:#fff;font:bold 12px arial;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th.yui-dt-desc{background:#333;}.yui-skin-sam .yui-pv-chartcontainer{padding:0 10px;}.yui-skin-sam .yui-pv-chart{height:250px;clear:right;margin:5px 0 0 0;color:#fff;}.yui-skin-sam .yui-pv-chartlegend div{float:right;margin:0 0 0 10px;_width:250px;}.yui-skin-sam .yui-pv-chartlegend dl{border:1px solid #999;padding:.2em 0 .2em .5em;zoom:1;margin:5px 0;}.yui-skin-sam .yui-pv-chartlegend dt{float:left;display:block;height:.7em;width:.7em;padding:0;}.yui-skin-sam .yui-pv-chartlegend dd{float:left;display:block;color:#fff;margin:0 1em 0 .5em;padding:0;font:11px arial;}.yui-skin-sam .yui-pv-minimized{height:35px;}.yui-skin-sam .yui-pv-minimized .bd{top:-3000px;}.yui-skin-sam .yui-pv-minimized .hd a.yui-pv-refresh{display:none;} +.yui-pb-bar,.yui-pb-mask{width:100%;height:100%}.yui-pb{position:relative;top:0;left:0;width:200px;height:20px;padding:0;border:0;margin:0;text-align:left}.yui-pb-mask{position:absolute;top:0;left:0;z-index:2}.yui-pb-mask div{width:50%;height:50%;background-repeat:no-repeat;padding:0;position:absolute}.yui-pb-tl{background-position:top left}.yui-pb-tr{background-position:top right;left:50%}.yui-pb-bl{background-position:bottom left;top:50%}.yui-pb-br{background-position:bottom right;left:50%;top:50%}.yui-pb-bar{margin:0;position:absolute;left:0;top:0;z-index:1}.yui-pb-ltr .yui-pb-bar{_position:static}.yui-pb-rtl .yui-pb-bar{background-position:right}.yui-pb-btt .yui-pb-bar{background-position:left bottom}.yui-pb-bar{background-color:blue}.yui-pb{border:thin solid #808080}.yui-skin-sam .yui-pb{background-color:transparent;border:solid #808080;border-width:1px 0}.yui-skin-sam .yui-pb-rtl,.yui-skin-sam .yui-pb-ltr{background-image:url(back-h.png);background-repeat:repeat-x}.yui-skin-sam .yui-pb-ttb,.yui-skin-sam .yui-pb-btt{background-image:url(back-v.png);background-repeat:repeat-y}.yui-skin-sam .yui-pb-bar{background-color:transparent}.yui-skin-sam .yui-pb-ltr .yui-pb-bar,.yui-skin-sam .yui-pb-rtl .yui-pb-bar{background-image:url(bar-h.png);background-repeat:repeat-x}.yui-skin-sam .yui-pb-ttb .yui-pb-bar,.yui-skin-sam .yui-pb-btt .yui-pb-bar{background-image:url(bar-v.png);background-repeat:repeat-y}.yui-skin-sam .yui-pb-mask{border:solid #808080;border-width:0 1px;margin:0 -1px}.yui-skin-sam .yui-pb-caption{color:#000;text-align:center;margin:0 auto}.yui-skin-sam .yui-pb-range{color:#a6a6a6} +.yui-resize{position:relative;zoom:1;z-index:0;}.yui-resize-wrap{zoom:1;}.yui-draggable{cursor:move;}.yui-resize .yui-resize-handle{position:absolute;z-index:1;font-size:0;margin:0;padding:0;zoom:1;height:1px;width:1px;}.yui-resize .yui-resize-handle-br{height:5px;width:5px;bottom:0;right:0;cursor:se-resize;z-index:2;zoom:1;}.yui-resize .yui-resize-handle-bl{height:5px;width:5px;bottom:0;left:0;cursor:sw-resize;z-index:2;zoom:1;}.yui-resize .yui-resize-handle-tl{height:5px;width:5px;top:0;left:0;cursor:nw-resize;z-index:2;zoom:1;}.yui-resize .yui-resize-handle-tr{height:5px;width:5px;top:0;right:0;cursor:ne-resize;z-index:2;zoom:1;}.yui-resize .yui-resize-handle-r{width:5px;height:100%;top:0;right:0;cursor:e-resize;zoom:1;}.yui-resize .yui-resize-handle-l{height:100%;width:5px;top:0;left:0;cursor:w-resize;zoom:1;}.yui-resize .yui-resize-handle-b{width:100%;height:5px;bottom:0;right:0;cursor:s-resize;zoom:1;}.yui-resize .yui-resize-handle-t{width:100%;height:5px;top:0;right:0;cursor:n-resize;zoom:1;}.yui-resize-proxy{position:absolute;border:1px dashed #000;visibility:hidden;z-index:1000;}.yui-resize-hover .yui-resize-handle,.yui-resize-hidden .yui-resize-handle{opacity:0;filter:alpha(opacity=0);}.yui-resize-ghost{opacity:.5;filter:alpha(opacity=50);}.yui-resize-knob .yui-resize-handle{height:6px;width:6px;}.yui-resize-knob .yui-resize-handle-tr{right:-3px;top:-3px;}.yui-resize-knob .yui-resize-handle-tl{left:-3px;top:-3px;}.yui-resize-knob .yui-resize-handle-bl{left:-3px;bottom:-3px;}.yui-resize-knob .yui-resize-handle-br{right:-3px;bottom:-3px;}.yui-resize-knob .yui-resize-handle-t{left:45%;top:-3px;}.yui-resize-knob .yui-resize-handle-r{right:-3px;top:45%;}.yui-resize-knob .yui-resize-handle-l{left:-3px;top:45%;}.yui-resize-knob .yui-resize-handle-b{left:45%;bottom:-3px;}.yui-resize-status{position:absolute;top:-999px;left:-999px;padding:2px;font-size:80%;display:none;zoom:1;z-index:9999;}.yui-resize-status strong,.yui-resize-status em{font-weight:normal;font-style:normal;padding:1px;zoom:1;}.yui-skin-sam .yui-resize .yui-resize-handle{background-color:#F2F2F2;zoom:1;}.yui-skin-sam .yui-resize .yui-resize-handle-active{background-color:#7D98B8;zoom:1;}.yui-skin-sam .yui-resize .yui-resize-handle-l,.yui-skin-sam .yui-resize .yui-resize-handle-r,.yui-skin-sam .yui-resize .yui-resize-handle-l-active,.yui-skin-sam .yui-resize .yui-resize-handle-r-active{height:100%;zoom:1;}.yui-skin-sam .yui-resize-knob .yui-resize-handle{border:1px solid #808080;}.yui-skin-sam .yui-resize-hover .yui-resize-handle-active{opacity:1;filter:alpha(opacity=100);}.yui-skin-sam .yui-resize-proxy{border:1px dashed #426FD9;}.yui-skin-sam .yui-resize-status{border:1px solid #A6982B;border-top:1px solid #D4C237;background-color:#FFEE69;color:#000;}.yui-skin-sam .yui-resize-status strong,.yui-skin-sam .yui-resize-status em{float:left;display:block;clear:both;padding:1px;text-align:center;}.yui-skin-sam .yui-resize .yui-resize-handle-inner-r,.yui-skin-sam .yui-resize .yui-resize-handle-inner-l{background:transparent url(layout_sprite.png) no-repeat 0 -5px;height:16px;width:5px;position:absolute;top:45%;}.yui-skin-sam .yui-resize .yui-resize-handle-inner-t,.yui-skin-sam .yui-resize .yui-resize-handle-inner-b{background:transparent url(layout_sprite.png) no-repeat -20px 0;height:5px;width:16px;position:absolute;left:50%;}.yui-skin-sam .yui-resize .yui-resize-handle-br{background-image:url(layout_sprite.png);background-repeat:no-repeat;background-position:-22px -62px;}.yui-skin-sam .yui-resize .yui-resize-handle-tr{background-image:url(layout_sprite.png);background-repeat:no-repeat;background-position:-22px -42px;}.yui-skin-sam .yui-resize .yui-resize-handle-tl{background-image:url(layout_sprite.png);background-repeat:no-repeat;background-position:-22px -82px;}.yui-skin-sam .yui-resize .yui-resize-handle-bl{background-image:url(layout_sprite.png);background-repeat:no-repeat;background-position:-22px -23px;}.yui-skin-sam .yui-resize-knob .yui-resize-handle-t,.yui-skin-sam .yui-resize-knob .yui-resize-handle-r,.yui-skin-sam .yui-resize-knob .yui-resize-handle-b,.yui-skin-sam .yui-resize-knob .yui-resize-handle-l,.yui-skin-sam .yui-resize-knob .yui-resize-handle-tl,.yui-skin-sam .yui-resize-knob .yui-resize-handle-tr,.yui-skin-sam .yui-resize-knob .yui-resize-handle-bl,.yui-skin-sam .yui-resize-knob .yui-resize-handle-br,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-t,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-r,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-b,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-l,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-tl,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-tr,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-bl,.yui-skin-sam .yui-resize-knob .yui-resize-handle-inner-br{background-image:none;}.yui-skin-sam .yui-resize-knob .yui-resize-handle-l,.yui-skin-sam .yui-resize-knob .yui-resize-handle-r,.yui-skin-sam .yui-resize-knob .yui-resize-handle-l-active,.yui-skin-sam .yui-resize-knob .yui-resize-handle-r-active{height:6px;width:6px;}.yui-skin-sam .yui-resize-textarea .yui-resize-handle-r{right:-8px;}.yui-skin-sam .yui-resize-textarea .yui-resize-handle-b{bottom:-8px;}.yui-skin-sam .yui-resize-textarea .yui-resize-handle-br{right:-8px;bottom:-8px;} +.yui-busy{cursor:wait!important;}.yui-toolbar-container fieldset,.yui-editor-container fieldset{padding:0;margin:0;border:0;}.yui-toolbar-container legend{display:none;}.yui-skin-sam .yui-toolbar-container .yui-button button,.yui-skin-sam .yui-toolbar-container .yui-button a,.yui-skin-sam .yui-toolbar-container .yui-button a:visited{font-size:0;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-select button,.yui-skin-sam .yui-toolbar-container .yui-toolbar-select a,.yui-skin-sam .yui-toolbar-container .yui-toolbar-select a:visited,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton button,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a:visited{font-size:12px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.up,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.down{font-size:0;line-height:0;padding:0;}.yui-toolbar-container .yui-toolbar-subcont{padding:.25em 0;zoom:1;}.yui-toolbar-container-collapsed .yui-toolbar-subcont{display:none;}.yui-toolbar-container .yui-toolbar-subcont:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-container span.yui-toolbar-draghandle{cursor:move;border-left:1px solid #999;border-right:1px solid #999;overflow:hidden;text-indent:77777px;width:2px;height:20px;display:block;clear:none;float:left;margin:0 0 0 .2em;}.yui-toolbar-container .yui-toolbar-titlebar.draggable{cursor:move;}.yui-toolbar-container .yui-toolbar-titlebar{position:relative;}.yui-toolbar-container .yui-toolbar-titlebar h2{font-weight:bold;letter-spacing:0;border:none;color:#000;margin:0;padding:.2em;}.yui-toolbar-container .yui-toolbar-titlebar h2 a{text-decoration:none;color:#000;cursor:default;}.yui-toolbar-container.yui-toolbar-grouped span.yui-toolbar-draghandle{height:40px;}.yui-toolbar-container .yui-toolbar-group{float:left;margin-right:.5em;zoom:1;}.yui-toolbar-container .yui-toolbar-group:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-container .yui-toolbar-group h3{font-size:75%;padding:0 0 0 .25em;margin:0;}.yui-toolbar-container span.yui-toolbar-separator{width:2px;padding:0;height:18px;margin:.2em 0 .2em .1em;display:none;float:left;}.yui-toolbar-container.yui-toolbar-grouped span.yui-toolbar-separator{height:45px;*height:50px;}.yui-toolbar-container.yui-toolbar-grouped .yui-toolbar-group span.yui-toolbar-separator{height:18px;display:block;}.yui-toolbar-container ul li{margin:0;padding:0;list-style-type:none;}.yui-toolbar-container .yui-toolbar-nogrouplabels h3{display:none;}.yui-toolbar-container .yui-push-button,.yui-toolbar-container .yui-color-button,.yui-toolbar-container .yui-menu-button{position:relative;cursor:pointer;}.yui-toolbar-container .yui-button .first-child,.yui-toolbar-container .yui-button .first-child a{height:100%;width:100%;overflow:hidden;font-size:0;}.yui-toolbar-container .yui-button-disabled{cursor:default;}.yui-toolbar-container .yui-button-disabled .yui-toolbar-icon{opacity:.5;filter:alpha(opacity=50);}.yui-toolbar-container .yui-button-disabled .up,.yui-toolbar-container .yui-button-disabled .down{opacity:.5;filter:alpha(opacity=50);}.yui-toolbar-container .yui-button a{overflow:hidden;}.yui-toolbar-container .yui-toolbar-select .first-child a{cursor:pointer;}.yui-toolbar-fontname-arial{font-family:Arial;}.yui-toolbar-fontname-arial-black{font-family:Arial Black;}.yui-toolbar-fontname-comic-sans-ms{font-family:Comic Sans MS;}.yui-toolbar-fontname-courier-new{font-family:Courier New;}.yui-toolbar-fontname-times-new-roman{font-family:Times New Roman;}.yui-toolbar-fontname-verdana{font-family:Verdana;}.yui-toolbar-fontname-impact{font-family:Impact;}.yui-toolbar-fontname-lucida-console{font-family:Lucida Console;}.yui-toolbar-fontname-tahoma{font-family:Tahoma;}.yui-toolbar-fontname-trebuchet-ms{font-family:Trebuchet MS;}.yui-toolbar-container .yui-toolbar-spinbutton{position:relative;}.yui-toolbar-container .yui-toolbar-spinbutton .first-child a{z-index:0;opacity:1;}.yui-toolbar-container .yui-toolbar-spinbutton a.up,.yui-toolbar-container .yui-toolbar-spinbutton a.down{position:absolute;display:block;right:0;cursor:pointer;z-index:1;padding:0;margin:0;}.yui-toolbar-container .yui-overlay{position:absolute;}.yui-toolbar-container .yui-overlay ul li{margin:0;list-style-type:none;}.yui-toolbar-container{z-index:1;}.yui-editor-container .yui-editor-editable-container{position:relative;z-index:0;width:100%;}.yui-editor-container .yui-editor-masked{background-color:#CCC;height:100%;width:100%;position:absolute;top:0;left:0;opacity:.5;filter:alpha(opacity=50);}.yui-editor-container iframe{border:0;padding:0;margin:0;zoom:1;display:block;}.yui-editor-container .yui-editor-editable{padding:0;margin:0;}.yui-editor-container .dompath{font-size:85%;}.yui-editor-panel .hd{text-align:left;position:relative;}.yui-editor-panel .hd h3{font-weight:bold;padding:.25em 0 .25em .25em;margin:0;}.yui-editor-panel .bd{width:100%;zoom:1;position:relative;}.yui-editor-panel .bd div.yui-editor-body-cont{padding:.25em .1em;zoom:1;}.yui-editor-panel .bd .gecko form{overflow:auto;}.yui-editor-panel .bd div.yui-editor-body-cont:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-editor-panel .ft{text-align:right;width:99%;float:left;clear:both;}.yui-editor-panel .ft span.tip{display:block;position:relative;padding:.5em .5em .5em 23px;text-align:left;zoom:1;}.yui-editor-panel label{clear:both;float:left;padding:0;width:100%;text-align:left;zoom:1;}.yui-editor-panel .gecko label{overflow:auto;}.yui-editor-panel label strong{float:left;width:6em;}.yui-editor-panel .removeLink{width:80%;text-align:right;}.yui-editor-panel label input{margin-left:.25em;float:left;}.yui-editor-panel .yui-toolbar-group{margin-bottom:.75em;}.yui-editor-panel .height-width{float:left;}.yui-editor-panel .height-width span{font-style:italic;display:block;float:left;overflow:visible;}.yui-editor-panel .height-width span.info{font-size:70%;margin-top:3px;float:none;} +.yui-editor-panel .yui-toolbar-bordersize,.yui-editor-panel .yui-toolbar-bordertype{font-size:75%;}.yui-editor-panel .yui-toolbar-container span.yui-toolbar-separator{border:none;}.yui-editor-panel .yui-toolbar-bordersize span a span,.yui-editor-panel .yui-toolbar-bordertype span a span{display:block;height:8px;left:4px;position:absolute;top:3px;_top:-5px;width:24px;text-indent:52px;font-size:0;}.yui-editor-panel .yui-toolbar-bordertype span a span.yui-toolbar-bordertype-solid{border-bottom:1px solid black;}.yui-editor-panel .yui-toolbar-bordertype span a span.yui-toolbar-bordertype-dotted{border-bottom:1px dotted black;}.yui-editor-panel .yui-toolbar-bordertype span a span.yui-toolbar-bordertype-dashed{border-bottom:1px dashed black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-0{*top:0;text-indent:0;font-size:75%;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-1{border-bottom:1px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-2{border-bottom:2px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-3{top:2px;*top:-5px;border-bottom:3px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-4{top:1px;*top:-5px;border-bottom:4px solid black;}.yui-editor-panel .yui-toolbar-bordersize span a span.yui-toolbar-bordersize-5{top:1px;*top:-5px;border-bottom:5px solid black;}.yui-toolbar-container .yui-toolbar-bordersize-menu,.yui-toolbar-container .yui-toolbar-bordertype-menu{width:95px!important;}.yui-toolbar-bordersize-menu .yuimenuitemlabel,.yui-toolbar-bordertype-menu .yuimenuitemlabel,.yui-toolbar-bordersize-menu .yuimenuitemlabel,.yui-toolbar-bordertype-menu .yuimenuitemlabel:hover{margin:0 3px 7px 17px;}.yui-toolbar-bordersize-menu .yuimenuitemlabel .checkedindicator,.yui-toolbar-bordertype-menu .yuimenuitemlabel .checkedindicator{position:absolute;left:-12px;*top:14px;*left:0;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-1 a{border-bottom:1px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-2 a{border-bottom:2px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-3 a{border-bottom:3px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-4 a{border-bottom:4px solid black;height:14px;}.yui-toolbar-bordersize-menu li.yui-toolbar-bordersize-5 a{border-bottom:5px solid black;height:14px;}.yui-toolbar-bordertype-menu li.yui-toolbar-bordertype-solid a{border-bottom:1px solid black;height:14px;}.yui-toolbar-bordertype-menu li.yui-toolbar-bordertype-dashed a{border-bottom:1px dashed black;height:14px;}.yui-toolbar-bordertype-menu li.yui-toolbar-bordertype-dotted a{border-bottom:1px dotted black;height:14px;}h2.yui-editor-skipheader,h3.yui-editor-skipheader{height:0;margin:0;padding:0;border:none;width:0;overflow:hidden;position:absolute;}.yui-toolbar-colors{width:133px;zoom:1;display:none;z-index:100;overflow:hidden;}.yui-toolbar-colors:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-colors a{height:9px;width:9px;float:left;display:block;overflow:hidden;text-indent:999px;margin:0;cursor:pointer;border:1px solid #F6F7EE;}.yui-toolbar-colors a:hover{border:1px solid black;}.yui-color-button-menu{overflow:visible;background-color:transparent;}.yui-toolbar-colors span{position:relative;display:block;padding:3px;overflow:hidden;float:left;width:100%;zoom:1;}.yui-toolbar-colors span:after{display:block;clear:both;visibility:hidden;content:'.';height:0;}.yui-toolbar-colors span em{height:35px;width:30px;float:left;display:block;overflow:hidden;text-indent:999px;margin:.75px;border:1px solid black;}.yui-toolbar-colors span strong{font-weight:normal;padding-left:3px;display:block;font-size:85%;float:left;width:65%;}.yui-toolbar-group-undoredo h3,.yui-toolbar-group-insertitem h3,.yui-toolbar-group-indentlist h3{width:68px;}.yui-toolbar-group-indentlist2 h3{width:122px;}.yui-toolbar-group-alignment h3{width:130px;}.yui-skin-sam .yui-editor-container{border:1px solid #808080;}.yui-skin-sam .yui-toolbar-container{zoom:1;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-titlebar{background:url(sprite.png) repeat-x 0 -200px;position:relative;}.yui-skin-sam .yui-editor-container .draggable .yui-toolbar-titlebar{cursor:move;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-titlebar h2{color:#000;font-weight:bold;margin:0;padding:.3em 1em;font-size:100%;text-align:left;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-group h3{color:#808080;font-size:75%;margin:1em 0 0;padding-bottom:0;padding-left:.25em;text-align:left;}.yui-toolbar-container span.yui-toolbar-separator{border:none;text-indent:33px;overflow:hidden;margin:0 .25em;}.yui-skin-sam .yui-toolbar-container{background-color:#F2F2F2;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-subcont{padding:0 1em .35em;border-bottom:1px solid #808080;}.yui-skin-sam .yui-toolbar-container-collapsed .yui-toolbar-titlebar{border-bottom:1px solid #808080;}.yui-skin-sam .yui-editor-container .visible .yui-menu-shadow,.yui-skin-sam .yui-editor-panel .visible .yui-menu-shadow{display:none;}.yui-skin-sam .yui-editor-container ul{list-style-type:none;margin:0;padding:0;}.yui-skin-sam .yui-editor-container ul li{list-style-type:none;margin:0;padding:0;}.yui-skin-sam .yui-toolbar-group ul li.yui-toolbar-groupitem{float:left;}.yui-skin-sam .yui-editor-container .dompath{background-color:#F2F2F2;border-top:1px solid #808080;color:#999;text-align:left;padding:.25em;}.yui-skin-sam .yui-toolbar-container .collapse{background:url(sprite.png) no-repeat 0 -400px;}.yui-skin-sam .yui-toolbar-container .collapsed{background:url(sprite.png) no-repeat 0 -350px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-titlebar span.collapse{cursor:pointer;position:absolute;top:4px;right:2px;display:block;overflow:hidden;height:15px;width:15px;text-indent:9999px;} +.yui-skin-sam .yui-toolbar-container .yui-push-button,.yui-skin-sam .yui-toolbar-container .yui-color-button,.yui-skin-sam .yui-toolbar-container .yui-menu-button{background:url(sprite.png) repeat-x 0 0;position:relative;display:block;height:22px;width:30px;_font-size:0;margin:0;border-color:#808080;color:#f2f2f2;border-style:solid;border-width:1px 0;zoom:1;}.yui-skin-sam .yui-toolbar-container .yui-push-button a,.yui-skin-sam .yui-toolbar-container .yui-color-button a,.yui-skin-sam .yui-toolbar-container .yui-menu-button a{padding-left:35px;height:20px;text-decoration:none;font-size:0;line-height:2;display:block;color:#000;overflow:hidden;white-space:nowrap;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a,.yui-skin-sam .yui-toolbar-container .yui-toolbar-select a{font-size:12px;}.yui-skin-sam .yui-toolbar-container .yui-push-button .first-child,.yui-skin-sam .yui-toolbar-container .yui-color-button .first-child,.yui-skin-sam .yui-toolbar-container .yui-menu-button .first-child{border-color:#808080;border-style:solid;border-width:0 1px;margin:0 -1px;display:block;position:relative;}.yui-skin-sam .yui-toolbar-container .yui-push-button-disabled .first-child,.yui-skin-sam .yui-toolbar-container .yui-color-button-disabled .first-child,.yui-skin-sam .yui-toolbar-container .yui-menu-button-disabled .first-child{border-color:#ccc;}.yui-skin-sam .yui-toolbar-container .yui-push-button-disabled a,.yui-skin-sam .yui-toolbar-container .yui-color-button-disabled a,.yui-skin-sam .yui-toolbar-container .yui-menu-button-disabled a{color:#A6A6A6;cursor:default;}.yui-skin-sam .yui-toolbar-container .yui-push-button-disabled,.yui-skin-sam .yui-toolbar-container .yui-color-button-disabled,.yui-skin-sam .yui-toolbar-container .yui-menu-button-disabled{border-color:#ccc;}.yui-skin-sam .yui-toolbar-container .yui-button .first-child{*left:0;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-fontname{width:135px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-heading{width:92px;}.yui-skin-sam .yui-toolbar-container .yui-button-hover{background:url(sprite.png) repeat-x 0 -1300px;border-color:#808080;}.yui-skin-sam .yui-toolbar-container .yui-button-selected{background:url(sprite.png) repeat-x 0 -1700px;border-color:#808080;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-nogrouplabels h3{display:none;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-nogrouplabels .yui-toolbar-group{margin-top:.75em;}.yui-skin-sam .yui-toolbar-container .yui-push-button span.yui-toolbar-icon,.yui-skin-sam .yui-toolbar-container .yui-color-button span.yui-toolbar-icon,.yui-skin-sam .yui-toolbar-container .yui-menu-button span.yui-toolbar-icon{display:block;position:absolute;top:2px;height:18px;width:18px;overflow:hidden;background:url(editor-sprite.gif) no-repeat 30px 30px;}.yui-skin-sam .yui-toolbar-container .yui-button-selected span.yui-toolbar-icon,.yui-skin-sam .yui-toolbar-container .yui-button-hover span.yui-toolbar-icon{background-image:url(editor-sprite-active.gif);}.yui-skin-sam .yui-toolbar-container .visible .yuimenuitemlabel{cursor:pointer;color:#000;*position:relative;}.yui-skin-sam .yui-toolbar-container .yui-button-menu{background-color:#fff;}.yui-skin-sam .yui-toolbar-container .yui-button-menu .yui-menu-body-scrolled{position:relative;}.yui-skin-sam div.yuimenu li.selected{background-color:#B3D4FF;}.yui-skin-sam div.yuimenu li.selected a.selected{color:#000;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-bold span.yui-toolbar-icon{background-position:0 0;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-strikethrough span.yui-toolbar-icon{background-position:0 -108px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-italic span.yui-toolbar-icon{background-position:0 -36px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-undo span.yui-toolbar-icon{background-position:0 -1326px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-redo span.yui-toolbar-icon{background-position:0 -1355px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-underline span.yui-toolbar-icon{background-position:0 -72px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-subscript span.yui-toolbar-icon{background-position:0 -180px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-superscript span.yui-toolbar-icon{background-position:0 -144px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-forecolor span.yui-toolbar-icon{background-position:0 -216px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-backcolor span.yui-toolbar-icon{background-position:0 -288px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifyleft span.yui-toolbar-icon{background-position:0 -324px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifycenter span.yui-toolbar-icon{background-position:0 -360px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifyright span.yui-toolbar-icon{background-position:0 -396px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-justifyfull span.yui-toolbar-icon{background-position:0 -432px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-indent span.yui-toolbar-icon{background-position:0 -720px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-outdent span.yui-toolbar-icon{background-position:0 -684px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-createlink span.yui-toolbar-icon{background-position:0 -792px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-insertimage span.yui-toolbar-icon{background-position:1px -756px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-left span.yui-toolbar-icon{background-position:0 -972px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-right span.yui-toolbar-icon{background-position:0 -936px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-inline span.yui-toolbar-icon{background-position:0 -900px;left:5px;} +.yui-skin-sam .yui-toolbar-container .yui-toolbar-block span.yui-toolbar-icon{background-position:0 -864px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-bordercolor span.yui-toolbar-icon{background-position:0 -252px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-removeformat span.yui-toolbar-icon{background-position:0 -1080px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-hiddenelements span.yui-toolbar-icon{background-position:0 -1044px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-insertunorderedlist span.yui-toolbar-icon{background-position:0 -468px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-insertorderedlist span.yui-toolbar-icon{background-position:0 -504px;left:5px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton .first-child{width:35px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton .first-child a{padding-left:2px;text-align:left;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton span.yui-toolbar-icon{display:none;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.up,.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.down{right:2px;background:url(editor-sprite.gif) no-repeat 0 -1222px;overflow:hidden;height:6px;width:7px;min-height:0;padding:0;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.up{top:2px;background-position:0 -1222px;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-spinbutton a.down{bottom:2px;background-position:0 -1187px;}.yui-skin-sam .yui-toolbar-container select{height:22px;border:1px solid #808080;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-select .first-child a{padding-left:5px;text-align:left;}.yui-skin-sam .yui-toolbar-container .yui-toolbar-select span.yui-toolbar-icon{background:url(editor-sprite.gif) no-repeat 0 -1144px;overflow:hidden;right:-2px;top:0;height:20px;}.yui-skin-sam .yui-editor-panel .yui-color-button-menu .bd{background-color:transparent;border:none;width:135px;}.yui-skin-sam .yui-color-button-menu .yui-toolbar-colors{border:1px solid #808080;}.yui-skin-sam .yui-editor-panel{padding:0;margin:0;border:none;background-color:transparent;overflow:visible;position:absolute;}.yui-skin-sam .yui-editor-panel .hd{margin:10px 0 0;padding:0;border:none;}.yui-skin-sam .yui-editor-panel .hd h3{color:#000;border:1px solid #808080;background:url(sprite.png) repeat-x 0 -200px;width:99%;position:relative;margin:0;padding:3px 0 0 0;font-size:93%;text-indent:5px;height:20px;}.yui-skin-sam .yui-editor-panel .bd{background-color:#F2F2F2;border-left:1px solid #808080;border-right:1px solid #808080;width:99%;margin:0;padding:0;overflow:visible;}.yui-skin-sam .yui-editor-panel ul{list-style-type:none;margin:0;padding:0;}.yui-skin-sam .yui-editor-panel ul li{margin:0;padding:0;}.yui-skin-sam .yui-editor-panel .yui-toolbar-container .yui-toolbar-subcont{padding:0;border:none;margin-top:.35em;}.yui-skin-sam .yui-editor-panel .yui-toolbar-bordersize,.yui-skin-sam .yui-editor-panel .yui-toolbar-bordertype{width:50px;}.yui-skin-sam .yui-editor-panel label{display:block;float:none;padding:4px 0;margin-bottom:7px;}.yui-skin-sam .yui-editor-panel label strong{font-weight:normal;font-size:93%;text-align:right;padding-top:2px;}.yui-skin-sam .yui-editor-panel label input{width:75%;}.yui-skin-sam .yui-editor-panel .createlink_target,.yui-skin-sam .yui-editor-panel .insertimage_target{width:auto;margin-right:5px;}.yui-skin-sam .yui-editor-panel .removeLink{width:98%;}.yui-skin-sam .yui-editor-panel label input.warning{background-color:#FFEE69;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group h3{color:#000;float:left;font-weight:normal;font-size:93%;margin:5px 0 0 0;padding:0 3px 0 0;text-align:right;}.yui-skin-sam .yui-editor-panel .height-width h3{margin:3px 0 0 10px;}.yui-skin-sam .yui-editor-panel .height-width{margin:3px 0 0 35px;*margin-left:14px;width:42%;*width:44%;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-border{width:190px;}.yui-skin-sam .yui-editor-panel .no-button .yui-toolbar-group-border{width:210px;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-padding{width:203px;_width:198px;}.yui-skin-sam .yui-editor-panel .no-button .yui-toolbar-group-padding{width:172px;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-padding h3{margin-left:25px;*margin-left:12px;}.yui-skin-sam .yui-editor-panel .yui-toolbar-group-textflow{width:182px;}.yui-skin-sam .yui-editor-panel .hd{background:none;}.yui-skin-sam .yui-editor-panel .ft{background-color:#F2F2F2;border:1px solid #808080;border-top:none;padding:0;margin:0 0 2px 0;}.yui-skin-sam .yui-editor-panel .hd span.close{background:url(sprite.png) no-repeat 0 -300px;cursor:pointer;display:block;height:16px;overflow:hidden;position:absolute;right:5px;text-indent:500px;top:2px;width:26px;}.yui-skin-sam .yui-editor-panel .ft span.tip{background-color:#EDF5FF;border-top:1px solid #808080;font-size:85%;}.yui-skin-sam .yui-editor-panel .ft span.tip strong{display:block;float:left;margin:0 2px 8px 0;}.yui-skin-sam .yui-editor-panel .ft span.tip span.icon{background:url(editor-sprite.gif) no-repeat 0 -1260px;display:block;height:20px;left:2px;position:absolute;top:8px;width:20px;}.yui-skin-sam .yui-editor-panel .ft span.tip span.icon-info{background-position:2px -1260px;}.yui-skin-sam .yui-editor-panel .ft span.tip span.icon-warn{background-position:2px -1296px;}.yui-skin-sam .yui-editor-panel .hd span.knob{position:absolute;height:10px;width:28px;top:-10px;left:25px;text-indent:9999px;overflow:hidden;background:url(editor-knob.gif) no-repeat 0 0;}.yui-skin-sam .yui-editor-panel .yui-toolbar-container{float:left;width:100%;background-image:none;border:none;}.yui-skin-sam .yui-editor-panel .yui-toolbar-container .bd{background-color:#fff;}.yui-editor-blankimage{background-image:url(blankimage.png);}.yui-skin-sam .yui-editor-container .yui-resize-handle-br{height:11px;width:11px;background-position:-20px -60px;background-color:transparent;}.yui-h-slider,.yui-v-slider,.yui-region-slider{position:relative;}.yui-h-slider .yui-slider-thumb,.yui-v-slider .yui-slider-thumb,.yui-region-slider .yui-slider-thumb{position:absolute;cursor:default;}.yui-skin-sam .yui-h-slider{background:url(bg-h.gif) no-repeat 5px 0;height:28px;width:228px;}.yui-skin-sam .yui-h-slider .yui-slider-thumb{top:4px;}.yui-skin-sam .yui-v-slider{background:url(bg-v.gif) no-repeat 12px 0;height:228px;width:48px;}.yui-skin-sam .yui-region-slider{height:228px;width:228px;} +.yui-navset .yui-nav li,.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{margin:0 .5em 0 0}.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{margin:0 0 .5em}.yui-navset .yui-content .yui-hidden{border:0;height:0;width:0;padding:0;position:absolute;left:-999999px;overflow:hidden;visibility:hidden}.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{width:6em}.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{width:auto}.yui-navset .yui-navset-left,.yui-navset-left{padding:0 0 0 6em}.yui-navset-right{padding:0 6em 0 0}.yui-navset-top,.yui-navset-bottom{padding:auto}.yui-nav,.yui-nav li{margin:0;padding:0;list-style:none}.yui-navset li em{font-style:normal}.yui-navset{position:relative;zoom:1}.yui-navset .yui-content,.yui-navset .yui-content div{zoom:1}.yui-navset .yui-content:after{content:'';display:block;clear:both}.yui-navset .yui-nav li,.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{display:inline-block;display:-moz-inline-stack;*display:inline;vertical-align:bottom;cursor:pointer;zoom:1}.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{display:block}.yui-navset .yui-nav a{position:relative}.yui-navset .yui-nav li a,.yui-navset-top .yui-nav li a,.yui-navset-bottom .yui-nav li a{display:block;display:inline-block;vertical-align:bottom;zoom:1}.yui-navset-left .yui-nav li a,.yui-navset-right .yui-nav li a{display:block}.yui-navset-bottom .yui-nav li a{vertical-align:text-top}.yui-navset .yui-nav li a em,.yui-navset-top .yui-nav li a em,.yui-navset-bottom .yui-nav li a em{display:block}.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{position:absolute;z-index:1}.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{position:static}.yui-navset .yui-navset-left .yui-nav,.yui-navset-left .yui-nav{left:0;right:auto}.yui-navset .yui-navset-right .yui-nav,.yui-navset-right .yui-nav{right:0;left:auto}.yui-skin-sam .yui-navset .yui-nav,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav{border:solid #2647a0;border-width:0 0 5px;zoom:1}.yui-skin-sam .yui-navset .yui-nav li,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav li{margin:0 .16em 0 0;padding:1px 0 0;zoom:1}.yui-skin-sam .yui-navset .yui-nav .selected,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav .selected{margin:0 .16em -1px 0}.yui-skin-sam .yui-navset .yui-nav a,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a{background:#d8d8d8 url(sprite.png) repeat-x;border:solid #a3a3a3;border-width:0 1px;color:#000;position:relative;text-decoration:none}.yui-skin-sam .yui-navset .yui-nav a em,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a em{border:solid #a3a3a3;border-width:1px 0 0;padding:.25em .75em;left:0;right:0;bottom:0;top:-1px;position:relative}.yui-skin-sam .yui-navset .yui-nav .selected a,.yui-skin-sam .yui-navset .yui-nav .selected a:focus,.yui-skin-sam .yui-navset .yui-nav .selected a:hover{background:#2647a0 url(sprite.png) repeat-x left -1400px;color:#fff}.yui-skin-sam .yui-navset .yui-nav a:hover,.yui-skin-sam .yui-navset .yui-nav a:focus{background:#bfdaff url(sprite.png) repeat-x left -1300px;outline:0}.yui-skin-sam .yui-navset .yui-nav .selected a em{padding:.35em .75em}.yui-skin-sam .yui-navset .yui-nav .selected a,.yui-skin-sam .yui-navset .yui-nav .selected a em{border-color:#243356}.yui-skin-sam .yui-navset .yui-content{background:#edf5ff}.yui-skin-sam .yui-navset .yui-content,.yui-skin-sam .yui-navset .yui-navset-top .yui-content{border:1px solid #808080;border-top-color:#243356;padding:.25em .5em}.yui-skin-sam .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 5px 0 0;Xposition:absolute;top:0;bottom:0}.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 0 0 5px}.yui-skin-sam .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset-right .yui-nav li{margin:0 0 .16em;padding:0 0 0 1px}.yui-skin-sam .yui-navset-right .yui-nav li{padding:0 1px 0 0}.yui-skin-sam .yui-navset-left .yui-nav .selected,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav .selected{margin:0 -1px .16em 0}.yui-skin-sam .yui-navset-right .yui-nav .selected{margin:0 0 .16em -1px}.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav a{border-width:1px 0}.yui-skin-sam .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 0 0 1px;padding:.2em .75em;top:auto;left:-1px}.yui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 1px 0 0;left:auto;right:-1px}.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-left .yui-nav .selected a,.yui-skin-sam .yui-navset-left .yui-nav a:hover,.yui-skin-sam .yui-navset-right .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav .selected a,.yui-skin-sam .yui-navset-right .yui-nav a:hover,.yui-skin-sam .yui-navset-bottom .yui-nav a,.yui-skin-sam .yui-navset-bottom .yui-nav .selected a,.yui-skin-sam .yui-navset-bottom .yui-nav a:hover{background-image:none}.yui-skin-sam .yui-navset-left .yui-content{border:1px solid #808080;border-left-color:#243356}.yui-skin-sam .yui-navset-bottom .yui-nav,.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav{border-width:5px 0 0}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav .selected,.yui-skin-sam .yui-navset-bottom .yui-nav .selected{margin:-1px .16em 0 0}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li,.yui-skin-sam .yui-navset-bottom .yui-nav li{padding:0 0 1px 0;vertical-align:top}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav a em,.yui-skin-sam .yui-navset-bottom .yui-nav a em{border-width:0 0 1px;top:auto;bottom:-1px} +.yui-skin-sam .yui-navset-bottom .yui-content,.yui-skin-sam .yui-navset .yui-navset-bottom .yui-content{border:1px solid #808080;border-bottom-color:#243356} +table.ygtvtable{margin-bottom:0;border:0;border-collapse:collapse}td.ygtvcell{border:0;padding:0}a.ygtvspacer{text-decoration:none;outline-style:none;display:block}.ygtvtn{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -5600px no-repeat;cursor:pointer}.ygtvtm{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -4000px no-repeat}.ygtvtmh,.ygtvtmhh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -4800px no-repeat}.ygtvtp{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -6400px no-repeat}.ygtvtph,.ygtvtphh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -7200px no-repeat}.ygtvln{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -1600px no-repeat;cursor:pointer}.ygtvlm{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 0 no-repeat}.ygtvlmh,.ygtvlmhh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -800px no-repeat}.ygtvlp{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -2400px no-repeat}.ygtvlph,.ygtvlphh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -3200px no-repeat;cursor:pointer}.ygtvloading{width:18px;height:22px;background:url(treeview-loading.gif) 0 0 no-repeat}.ygtvdepthcell{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -8000px no-repeat}.ygtvblankdepthcell{width:18px;height:22px}* html .ygtvchildren{height:2%}.ygtvlabel,.ygtvlabel:link,.ygtvlabel:visited,.ygtvlabel:hover{margin-left:2px;text-decoration:none;background-color:white;cursor:pointer}.ygtvcontent{cursor:default}.ygtvspacer{height:22px;width:18px}.ygtvfocus{background-color:#c0e0e0;border:0}.ygtvfocus .ygtvlabel,.ygtvfocus .ygtvlabel:link,.ygtvfocus .ygtvlabel:visited,.ygtvfocus .ygtvlabel:hover{background-color:#c0e0e0}.ygtvfocus a{outline-style:none}.ygtvok{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -8800px no-repeat}.ygtvok:hover{background:url(treeview-sprite.gif) 0 -8844px no-repeat}.ygtvcancel{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -8822px no-repeat}.ygtvcancel:hover{background:url(treeview-sprite.gif) 0 -8866px no-repeat}.ygtv-label-editor{background-color:#f2f2f2;border:1px solid silver;position:absolute;display:none;overflow:hidden;margin:auto;z-index:9000}.ygtv-edit-TextNode{width:190px}.ygtv-edit-TextNode .ygtvcancel,.ygtv-edit-TextNode .ygtvok{border:0}.ygtv-edit-TextNode .ygtv-button-container{float:right}.ygtv-edit-TextNode .ygtv-input input{width:140px}.ygtv-edit-DateNode .ygtvcancel{border:0}.ygtv-edit-DateNode .ygtvok{display:none}.ygtv-edit-DateNode .ygtv-button-container{text-align:right;margin:auto}.ygtv-highlight .ygtv-highlight1,.ygtv-highlight .ygtv-highlight1 .ygtvlabel{background-color:blue;color:white}.ygtv-highlight .ygtv-highlight2,.ygtv-highlight .ygtv-highlight2 .ygtvlabel{background-color:silver}.ygtv-highlight .ygtv-highlight0 .ygtvfocus .ygtvlabel,.ygtv-highlight .ygtv-highlight1 .ygtvfocus .ygtvlabel,.ygtv-highlight .ygtv-highlight2 .ygtvfocus .ygtvlabel{background-color:#c0e0e0}.ygtv-highlight .ygtvcontent{padding-right:1em}.ygtv-checkbox .ygtv-highlight0 .ygtvcontent{padding-left:1em;background:url(check0.gif) no-repeat}.ygtv-checkbox .ygtv-highlight0 .ygtvfocus.ygtvcontent,.ygtv-checkbox .ygtv-highlight1 .ygtvfocus.ygtvcontent,.ygtv-checkbox .ygtv-highlight2 .ygtvfocus.ygtvcontent{background-color:#c0e0e0}.ygtv-checkbox .ygtv-highlight1 .ygtvcontent{padding-left:1em;background:url(check1.gif) no-repeat}.ygtv-checkbox .ygtv-highlight2 .ygtvcontent{padding-left:1em;background:url(check2.gif) no-repeat} + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/slider.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/slider.css new file mode 100644 index 0000000..3947edc --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/slider.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-h-slider,.yui-v-slider,.yui-region-slider{position:relative;}.yui-h-slider .yui-slider-thumb,.yui-v-slider .yui-slider-thumb,.yui-region-slider .yui-slider-thumb{position:absolute;cursor:default;}.yui-skin-sam .yui-h-slider{background:url(bg-h.gif) no-repeat 5px 0;height:28px;width:228px;}.yui-skin-sam .yui-h-slider .yui-slider-thumb{top:4px;}.yui-skin-sam .yui-v-slider{background:url(bg-v.gif) no-repeat 12px 0;height:228px;width:48px;}.yui-skin-sam .yui-region-slider{height:228px;width:228px;} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-active.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-active.png new file mode 100644 index 0000000000000000000000000000000000000000..fa58c5030e76082c84e38342cf6722c723ad2fd2 GIT binary patch literal 280 zcmV+z0q6dSP)N~-|K;%i-0c73 z@c-iO|KRQa-|hd~QeFE1003M`L_t(|+U&?l5`sVg1i`WZK}Epr|6dhmytLs92=mel z9uoULP6;mwyM%qhIpHzkHQ|(SNO(*5TD8?y@wq9xG<+26t_AN^`$=39HtEMPCOjwP e%l`;(0R{kdKn;SADLBOd00006$Gh9E#3p9{H-P6S}q~camLV^=3&tj%#_Xa_x2_Xl57U&w-9pX85Q9;Im dv4Me^VIeE)+1pK9I)PdkJYD@<);T3K0RYcxInw|D literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-focus.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-focus.png new file mode 100644 index 0000000000000000000000000000000000000000..167d71eb721ba9b85c6601f9077d5c39faa4ebd2 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0zhoU!3-pmJXhxdDVB6cUq=RpYd5a=M;HP5k|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5XI0Jk_Tx)0S05bpo|DSu#^)isf zToU9L{Qp10^;5h+0~ypkT^vIyZY3ooII;39W@>hC5M-JVa^Poyu7TYlo?{mkWE>b9 b7?>Frva+7N-L$0>sD;7P)z4*}Q$iB}D9ShR literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-hover.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..167d71eb721ba9b85c6601f9077d5c39faa4ebd2 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0zhoU!3-pmJXhxdDVB6cUq=RpYd5a=M;HP5k|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5XI0Jk_Tx)0S05bpo|DSu#^)isf zToU9L{Qp10^;5h+0~ypkT^vIyZY3ooII;39W@>hC5M-JVa^Poyu7TYlo?{mkWE>b9 b7?>Frva+7N-L$0>sD;7P)z4*}Q$iB}D9ShR literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..b33a93ff2dc2039bd24e4ea3b75ecf4bb3295f84 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0zhoU!3-pmJXhxdDVB6cUq=RpYd5a=M;HP5k|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5XI0Jk_TpJo1fXx5@|JyBHuocK+ zE(!7r{{Nrh`YB$Zfeh-NE{-7;w~`VPoLG4lGc~(62r^9wIqgTe~DWM4f1sXSq literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..73634d6a22c4377060f49217b63f31b59fe22d51 GIT binary patch literal 3745 zcmd^C`B&0g_x=DPilSwrm^nqWnUq#eWm--*^_u07bqmX(Ow1J2va6=14V2nkPNmhY z>pbKX8aQGaYNeQ>fCJzZNCKiJFLv*Dec%7#eSXEiNvKM52X-1&Ks5Iy%nf@%RFP{l#ybSs9bX znx39!vqywNp;#-n3j!vm-TRDQt5)(2~rzV*2|SO56Nspdahr;-Zd(t^W+rlQGslR&tF(rp5JW>HfmW$*F;XK?Y-}yXP~PH%X`W*Y(S$r)L@{ zjk7{I|6FrR>(CIh;$1b5Hz{3Mz<9sg;aNH-5*-Nb{o31i0M}>f-(2&)zWrl|NG#ra zy0NgNbYC#dIlJ#$lc_OtJno%dgL$k5BoeQ{`qAG_A88ZZm-{BkTPN%HPSkCrS8SPA zQHhLkVaRw*@`G^hMGD1Q^X1_Xi zUWE&unOh&s6s4t^9W0!!NNs+kRa-}&?G2tI5Ei| zejK}{Mo&?kr#D=CT5Y)D+G2eC$+(Xbmo<5KwT;H9JRVQt6kiB|S(BD767-I5-vVVZ|jgA2T5P$4tIU|r9SQK>hzc#TLptZ8*+Ul!`b)`vCQ}P z0hEqYj2dd4I|$89%=kg3dSS=@!j73?$C|KXE!eRn>{tXwxF54ik7$E%T!y8j{|k)1 z|0-1@|HP&M%vr!x0X=~otH+L=#Rh1h+QDc80G$g#S5T;3Wa?uw)rmq)B~!I2)HVv$ zheC~~tkU=w?uOJa`|KOdlFD+4X+PI3BC!G6P_+QDhD?2h9n-)F^)NycjL;1ep@V8y zK=WZ}GYU&vm87H^7YMS6A#6ll6-;i$B>x}S>D=qd$wp5Ca+RKF28J6>O#9~?uCEbR zV!E6O(35W+bJVuow=(JdT9@WsK35qz*;(nCk6+uZQ|S<+Q;)6}hn$$J%lY$8&!Zl@ z7(Tmt<+R~vd;oV$`-DfhRyU>B`O*bq^MFK`f zM(ltBp!K{K%Q6z6g@0X_fX3fhdzw!CmKLGbeF3%ABbcSd4pb%PK)Q>ZN{m}iq*MU^ zxM?i~QzQK`7hUfbcN2hX2X0+juvm9nzPUMehR{OVa~68Q+1dHYo9+Y+O|)|Dc}zQM z%?(Bh3L3O0aDZ|nb4_$W&HKjTa_oHlO*1owj#<-i1-5@QzU0XFXM$kx3Cwg~^QP+9 zsOF!yv`D<#r^S9*`r=^+t*e)PKRMlg8alGe(0N-*3xH`jFbF4CDaePf-Lq$+ z_JWWJIAyF4s2>SbA<4EwIu+}0fd}D+BZ4k?f;_pHW%lXAcRWpjqXqXN?Y(dPcturr z8NGFTUYUPOY=32Sj;IN7?DQ+tKi)d|L}Z03^qwkv_FhMxWFvnDIn&tKSOpYwko}qb zxly;Wv{c{|$?2@E@u0sxwj=v&(D_$direR70z3VZANNd)Mx9HNDE8s|BH}l!AZrzd zQUalNCI^9DPg8GXDc;zn0{j8P(m;pYA%|$-PLFdbqP(Y2UU?AkI=Cj&yaJeTo5){2 zR}3k2c`yZ7sE~6te`R8pu+cC|F98?2En&wL%eLaM4+wu87Vo8qZ}}TsS`5BHT4nf= z0I(h=RP0)Bs!&=2l$ZO01e>p~WMKBWwdQk&*kDOd6)j3&?E7wsexnPlXU(O# zuljo1$*Bf4%F4=Zs(G77cyISv`6j5_hOg1kXw|5*Q_2cB!KH^O)fs88-5!20+s+A@ zt{=%a$}-0wlF2Srgt%-)iaGVVqRQvzwCDM7=d@ah>um|??C3nHmk}~l3Q6~;yOg(Tj}AGmP=BBZ6WFh3T>G>E_~0 zV=q;isVW)_KE+Y|5G3X?ue7353?5Jrb^K0XiJBt6gpfE1@hUtOKwlmL<#>et)jQMs zP9@s1sBK_iAkh1R_KwibXvVJJ`nAKzZNyYH-7 zhi$cO?>yczO?*90W))nk{q3pyW{0gCBL)WtA78*;DwF!O-=PU&ilrH~1OnlMf_K_@ zglJW`k*`nnNv?f(?QnKt!5LL{eekGbsROFm4>=Y1>vh^3t|_UmsHlj}RV&8f^y*%9 zeHoZIJ*7mCQu~?DuOj30)8c>lZSJ?4yU}K5is{N9i-OgZTs)lHW`>_HP0aa}n%6Yk zV6-vELYl1nb1J`y_TjCf)Bb@kbu>^|?YQ~eSEtlWr-L6L)BBdFN}-~~G|TOyFNRHu zii+S1UXuoR-?YKhD?gW4o%G??1oq*?i@(#X&(~#USBn-1ZB>ia1_jX(FY3A7@_uze zq%Q1mkV_LPTJS>Sp|wcxd-Z<5;Xk~~eP9N4qO@_{I&G6J(jvu2Hh#;nHCmD>tRw}o zDU{ymFf`QE6xcH3v|B*CS6+VY+K4!AXqTeok*2z8rG)wNbXu&Bnrfj9yimX_JXWiG z&19R>QY{kL|IM>pAHTC+hN6)Vc;Rkpv-< z^ob-bB1w@*QX`UJM3Nqnq(dZuh$IA&w3bLxCX%4UC79}psI0)>Vr)X+i2aoEI6>}f z8^&VE1|{8&lI}rWHb$+BLlCd(5wAjsS3$(9P$Frys+uj-aX-Q_PQfuw$#EI_|21-* z5TBMFPQ(JPC&`gyA}9;2nEFqdMPkPuV#mOk5qYfyp&ut?@Dno(k}@Bb;(yn( zzhaY<@5iXhwGuOnwIR+>4o308=v)P}oP$xe0GbIw^A*sKuVr*lSl2nKn23$2%Wxt_ zwFx6;%MbAaTB4Z5%z!Wz5KM0b^9_QzfMB|+F>}n%$G&w-RGl`sHbqp235x$P&5;k)YU@q zX~|W0i~~FFP(c5lWc2I#uITH5^p)tlV8!RdP9>4uKJAn2xd_I#4K1pNO?5X7eS$$g zh- z3`S&i*Iv?T3X*;?B0=v2-|IE^hO&gQTJLW{5jDf@y-#Ph^7@Q^F70D{FSTsU*EW4i=9hj%JltBYw_d$-48>? zj67G@+QG#0!q)P?`BuOGf9?&FMG;WsvPY65^mUaonrGoX-b8F za^G3nBtU5zoGYm>j(H>Y1+6GqIoRSXPk7}IEELd7aSKMHpI@$Yce!a3;6(Pgqj8z0 zFYS5p_vVr3*$;S`>A$)NBjbd!Bwi14|EVS+`9BbFad1CWY>!R+4|+`f{{R30 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.psd b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.psd new file mode 100644 index 0000000000000000000000000000000000000000..fff2c3471308fed4c93ef4961ea1cd729b41bdca GIT binary patch literal 118162 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 literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/tabview.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/tabview.css new file mode 100644 index 0000000..9c3a358 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/tabview.css @@ -0,0 +1,8 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +.yui-navset .yui-nav li,.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{margin:0 .5em 0 0}.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{margin:0 0 .5em}.yui-navset .yui-content .yui-hidden{border:0;height:0;width:0;padding:0;position:absolute;left:-999999px;overflow:hidden;visibility:hidden}.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{width:6em}.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{width:auto}.yui-navset .yui-navset-left,.yui-navset-left{padding:0 0 0 6em}.yui-navset-right{padding:0 6em 0 0}.yui-navset-top,.yui-navset-bottom{padding:auto}.yui-nav,.yui-nav li{margin:0;padding:0;list-style:none}.yui-navset li em{font-style:normal}.yui-navset{position:relative;zoom:1}.yui-navset .yui-content,.yui-navset .yui-content div{zoom:1}.yui-navset .yui-content:after{content:'';display:block;clear:both}.yui-navset .yui-nav li,.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{display:inline-block;display:-moz-inline-stack;*display:inline;vertical-align:bottom;cursor:pointer;zoom:1}.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{display:block}.yui-navset .yui-nav a{position:relative}.yui-navset .yui-nav li a,.yui-navset-top .yui-nav li a,.yui-navset-bottom .yui-nav li a{display:block;display:inline-block;vertical-align:bottom;zoom:1}.yui-navset-left .yui-nav li a,.yui-navset-right .yui-nav li a{display:block}.yui-navset-bottom .yui-nav li a{vertical-align:text-top}.yui-navset .yui-nav li a em,.yui-navset-top .yui-nav li a em,.yui-navset-bottom .yui-nav li a em{display:block}.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{position:absolute;z-index:1}.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{position:static}.yui-navset .yui-navset-left .yui-nav,.yui-navset-left .yui-nav{left:0;right:auto}.yui-navset .yui-navset-right .yui-nav,.yui-navset-right .yui-nav{right:0;left:auto}.yui-skin-sam .yui-navset .yui-nav,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav{border:solid #2647a0;border-width:0 0 5px;zoom:1}.yui-skin-sam .yui-navset .yui-nav li,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav li{margin:0 .16em 0 0;padding:1px 0 0;zoom:1}.yui-skin-sam .yui-navset .yui-nav .selected,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav .selected{margin:0 .16em -1px 0}.yui-skin-sam .yui-navset .yui-nav a,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a{background:#d8d8d8 url(sprite.png) repeat-x;border:solid #a3a3a3;border-width:0 1px;color:#000;position:relative;text-decoration:none}.yui-skin-sam .yui-navset .yui-nav a em,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a em{border:solid #a3a3a3;border-width:1px 0 0;padding:.25em .75em;left:0;right:0;bottom:0;top:-1px;position:relative}.yui-skin-sam .yui-navset .yui-nav .selected a,.yui-skin-sam .yui-navset .yui-nav .selected a:focus,.yui-skin-sam .yui-navset .yui-nav .selected a:hover{background:#2647a0 url(sprite.png) repeat-x left -1400px;color:#fff}.yui-skin-sam .yui-navset .yui-nav a:hover,.yui-skin-sam .yui-navset .yui-nav a:focus{background:#bfdaff url(sprite.png) repeat-x left -1300px;outline:0}.yui-skin-sam .yui-navset .yui-nav .selected a em{padding:.35em .75em}.yui-skin-sam .yui-navset .yui-nav .selected a,.yui-skin-sam .yui-navset .yui-nav .selected a em{border-color:#243356}.yui-skin-sam .yui-navset .yui-content{background:#edf5ff}.yui-skin-sam .yui-navset .yui-content,.yui-skin-sam .yui-navset .yui-navset-top .yui-content{border:1px solid #808080;border-top-color:#243356;padding:.25em .5em}.yui-skin-sam .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 5px 0 0;Xposition:absolute;top:0;bottom:0}.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 0 0 5px}.yui-skin-sam .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset-right .yui-nav li{margin:0 0 .16em;padding:0 0 0 1px}.yui-skin-sam .yui-navset-right .yui-nav li{padding:0 1px 0 0}.yui-skin-sam .yui-navset-left .yui-nav .selected,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav .selected{margin:0 -1px .16em 0}.yui-skin-sam .yui-navset-right .yui-nav .selected{margin:0 0 .16em -1px}.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav a{border-width:1px 0}.yui-skin-sam .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 0 0 1px;padding:.2em .75em;top:auto;left:-1px}.yui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 1px 0 0;left:auto;right:-1px}.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-left .yui-nav .selected a,.yui-skin-sam .yui-navset-left .yui-nav a:hover,.yui-skin-sam .yui-navset-right .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav .selected a,.yui-skin-sam .yui-navset-right .yui-nav a:hover,.yui-skin-sam .yui-navset-bottom .yui-nav a,.yui-skin-sam .yui-navset-bottom .yui-nav .selected a,.yui-skin-sam .yui-navset-bottom .yui-nav a:hover{background-image:none}.yui-skin-sam .yui-navset-left .yui-content{border:1px solid #808080;border-left-color:#243356}.yui-skin-sam .yui-navset-bottom .yui-nav,.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav{border-width:5px 0 0}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav .selected,.yui-skin-sam .yui-navset-bottom .yui-nav .selected{margin:-1px .16em 0 0}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li,.yui-skin-sam .yui-navset-bottom .yui-nav li{padding:0 0 1px 0;vertical-align:top}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav a em,.yui-skin-sam .yui-navset-bottom .yui-nav a em{border-width:0 0 1px;top:auto;bottom:-1px} +.yui-skin-sam .yui-navset-bottom .yui-content,.yui-skin-sam .yui-navset .yui-navset-bottom .yui-content{border:1px solid #808080;border-bottom-color:#243356} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-loading.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..0bbf3bc0c0e5e635553e8d1bf9ceddefbc402396 GIT binary patch literal 2673 zcmchY_gj;P7RTSb83YJ1>=8y5ONL=ZcEgk+C?FydumNNz8c=c6`n&|fmMu_HHG%^w zNLVjHyfy)hAgHK_Kxkz+0Ktm5M|X*?y?g!o_3yv`{_^F^wY9YuFJ3GxEUd1s-nnz<)vH(c?%i8n zUVirM+2rIT007UQKY#e};oRKZty{MqJa}MhYina;bNBAu-+udTYHDhBcJ|n@WA*j* z-+lL;iHS*OX6D|#dm|zu!o$ON?b=mbT)bh!26uP&kdP1u2Zx!N8486$B9X?&$DclZ zdgI28>FMdk#l`#g@Bj4EPc=0)2M!!4EG!%z9?s6rzI5r**|TSdhK8)HtXf)HHgDc+ zZEek9Fk)k4xm@nHZQC3j9o^jACMG6~jg9m3^EYnX2*Yq^XJ>6~?X_#y4jnqQbLUQp zM6z$+zMp^o*}}p?p-?n8H=jOzx~Zv&N~Km+RkgLX9X@>c=FOXxm6dsUd1NvZ zX=yul?BMZua=F~p)O7py?EwJ+w{PD*dGh2hzx?v((WCP6au$mb!vmnqSpF6-9Ona(JQT#e>!KODwxYzG5#S|?M#v6eD#mgO^`=~9EL;yL&>*dd5*+XG=_`^3=CG25PbLa+LJ%N(PW_s z=_-TaM{SB!w(n7k+dMDN2G6VPqUA$u7F4m@ABAZ1D`*UMfe}E6csJU}J1Trmp#~7hZ5QSGpNvd1Uz$!Rf3q28pgSj9o zx?zwoWa8GYK@TOz^)mp#V2_VR5WfJ0W9BSSbn+cKb z7B9l9)K#s!?PSt;g%c8u;y7rd?hkP%>vq5BY=N>c=98V=+T&RSPgSu|E(FAK>B?vNN1 zPszwcbxJ?Oh|1pGd!9?gxzSWOR8o=x5!rGh+6r3hBL-14aTaAQxvJ|Y-S_m4niV2S zK@?}-9Dkhg<+w{Ny!vjyp-QmjyGmIW1DFB{k>P2=8cm~9M^_P#8?JFDumGEPaqJvf zZ{f;B#CG;H7q8a_hQ$pR6%%6So8vKM+W+cNPE_TI46^dn9q@qBr@1bUgxcPGB*b-i z3Hx_0(Esy5KKx^Y0yfgB6~}t>@!ctk>J|!vgVRhE2CPQ;AOKY2y%5nM@YF^ZMS~q}%L-n>Lpor#4w48UHYViOt={{43LMRvkIp+rkbs*s; z14}4q0y6`s8DL?uo-~*R@5tnFsC1DR#BGxT8fA20u_o?`0iDNI6lf;^$@AkR1dPTz z>XF1ZAqNjU95c@Vn59Wo;Z6b(YG+L$xy3(?j2I*vQ>PmzMEdh`yw3=)E}JYMDG|*x mDkGVJ;D)fXhxDI?kcM(ish)HppA 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 U{p-H~9KZ}Pzz8h7+YkZ(JNT^25dZ)H literal 0 HcmV?d00001 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview.css new file mode 100644 index 0000000..8fa8da8 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +table.ygtvtable{margin-bottom:0;border:0;border-collapse:collapse}td.ygtvcell{border:0;padding:0}a.ygtvspacer{text-decoration:none;outline-style:none;display:block}.ygtvtn{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -5600px no-repeat;cursor:pointer}.ygtvtm{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -4000px no-repeat}.ygtvtmh,.ygtvtmhh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -4800px no-repeat}.ygtvtp{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -6400px no-repeat}.ygtvtph,.ygtvtphh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -7200px no-repeat}.ygtvln{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -1600px no-repeat;cursor:pointer}.ygtvlm{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 0 no-repeat}.ygtvlmh,.ygtvlmhh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -800px no-repeat}.ygtvlp{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -2400px no-repeat}.ygtvlph,.ygtvlphh{width:18px;height:22px;cursor:pointer;background:url(treeview-sprite.gif) 0 -3200px no-repeat;cursor:pointer}.ygtvloading{width:18px;height:22px;background:url(treeview-loading.gif) 0 0 no-repeat}.ygtvdepthcell{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -8000px no-repeat}.ygtvblankdepthcell{width:18px;height:22px}* html .ygtvchildren{height:2%}.ygtvlabel,.ygtvlabel:link,.ygtvlabel:visited,.ygtvlabel:hover{margin-left:2px;text-decoration:none;background-color:white;cursor:pointer}.ygtvcontent{cursor:default}.ygtvspacer{height:22px;width:18px}.ygtvfocus{background-color:#c0e0e0;border:0}.ygtvfocus .ygtvlabel,.ygtvfocus .ygtvlabel:link,.ygtvfocus .ygtvlabel:visited,.ygtvfocus .ygtvlabel:hover{background-color:#c0e0e0}.ygtvfocus a{outline-style:none}.ygtvok{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -8800px no-repeat}.ygtvok:hover{background:url(treeview-sprite.gif) 0 -8844px no-repeat}.ygtvcancel{width:18px;height:22px;background:url(treeview-sprite.gif) 0 -8822px no-repeat}.ygtvcancel:hover{background:url(treeview-sprite.gif) 0 -8866px no-repeat}.ygtv-label-editor{background-color:#f2f2f2;border:1px solid silver;position:absolute;display:none;overflow:hidden;margin:auto;z-index:9000}.ygtv-edit-TextNode{width:190px}.ygtv-edit-TextNode .ygtvcancel,.ygtv-edit-TextNode .ygtvok{border:0}.ygtv-edit-TextNode .ygtv-button-container{float:right}.ygtv-edit-TextNode .ygtv-input input{width:140px}.ygtv-edit-DateNode .ygtvcancel{border:0}.ygtv-edit-DateNode .ygtvok{display:none}.ygtv-edit-DateNode .ygtv-button-container{text-align:right;margin:auto}.ygtv-highlight .ygtv-highlight1,.ygtv-highlight .ygtv-highlight1 .ygtvlabel{background-color:blue;color:white}.ygtv-highlight .ygtv-highlight2,.ygtv-highlight .ygtv-highlight2 .ygtvlabel{background-color:silver}.ygtv-highlight .ygtv-highlight0 .ygtvfocus .ygtvlabel,.ygtv-highlight .ygtv-highlight1 .ygtvfocus .ygtvlabel,.ygtv-highlight .ygtv-highlight2 .ygtvfocus .ygtvlabel{background-color:#c0e0e0}.ygtv-highlight .ygtvcontent{padding-right:1em}.ygtv-checkbox .ygtv-highlight0 .ygtvcontent{padding-left:1em;background:url(check0.gif) no-repeat}.ygtv-checkbox .ygtv-highlight0 .ygtvfocus.ygtvcontent,.ygtv-checkbox .ygtv-highlight1 .ygtvfocus.ygtvcontent,.ygtv-checkbox .ygtv-highlight2 .ygtvfocus.ygtvcontent{background-color:#c0e0e0}.ygtv-checkbox .ygtv-highlight1 .ygtvcontent{padding-left:1em;background:url(check1.gif) no-repeat}.ygtv-checkbox .ygtv-highlight2 .ygtvcontent{padding-left:1em;background:url(check2.gif) no-repeat} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/wait.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/wait.gif new file mode 100644 index 0000000000000000000000000000000000000000..471c1a4f93f2cabf0b3a85c3ff8e0a8aadefc548 GIT binary patch literal 1100 zcmZwFZA@EL90u^)S14;kcS~P51JcqXyBK7YjR|$m*3qt)1nqFnf*+(nyIT_zZIrbc zP70+hE$ePOAcE2K4FU;V;KM+=xUiQtnG(k(Qx;;(oQVNl47kM11c$9(j7iV=cuw*= z&;L26aeaM*8AVX!4nUmF3luezO5JukyN8Fbj*JY)E9#Hd|0*@ZIv{eO*Nb# z12yCIrOhLLJlbn33DTB}t(F_b2bV4~y*j=}%v9m90(t13QX1^b_==P$D+H{5*5Mu? z8gKY>BXXf^7@!+sCzFj+>XgJsqfc(1Ya(r=#J=3 zlZtj9{~(p*xA$9X2mMtN6e0bM#^36uHAhJ9Q&;+@HQ_ThCJ=yPPcaaStzMs1DHP_0 zvw_E92pgO+s83$0SnZp{u*pvQ$A3#Rftg(VD(=52XCTzUftd4T-22$PQrgIR*gHx4 z{43C_yk?5j?(i$Mual4dFf?{<9Wn}qfaB%>iNwkdu&q!m&h2IcZ$2Th!C8}<*_&Pr zyKl`OZw8N)3D^4?RK}UoD=o00gbKYHy=yv32mZ9Dl8aIS8x^Z$2?NwcBLzFmZOtoW zzN62&u*QDIz{Fy}^YAXY&Txmg7ATSAhAr8K5fZbFZ*SFa$_qE2L|VVFHOI{wKE8B_ zGXV2p-56OO`rc4Z7g3zbj)2_3YjK$((`OUqD%*mgvS`YELYsVW1or1)YW%;)D$oE>#r zQ3z|D(W$Eg`c?NY^+fD&+nctrc25@u47U__J8-QW7NqK!$T9C@*SpuaHyFRRpIGae rj_Lao#za}+eaj_<`F9!mRdtBiaY8;H -1; + } + } else { + YAHOO.log('hasClass called with invalid arguments', 'warn', 'Dom'); + } + + return ret; + }, + + /** + * Adds a class name to a given element or collection of elements. + * @method addClass + * @param {String | HTMLElement | Array} el The element or collection to add the class to + * @param {String} className the class name to add to the class attribute + * @return {Boolean | Array} A pass/fail boolean or array of booleans + */ + addClass: function(el, className) { + return Y.Dom.batch(el, Y.Dom._addClass, className); + }, + + _addClass: function(el, className) { + var ret = false, + current; + + if (el && className) { + current = Y.Dom._getAttribute(el, CLASS_NAME) || EMPTY; + if ( !Y.Dom._hasClass(el, className) ) { + Y.Dom.setAttribute(el, CLASS_NAME, trim(current + SPACE + className)); + ret = true; + } + } else { + YAHOO.log('addClass called with invalid arguments', 'warn', 'Dom'); + } + + return ret; + }, + + /** + * Removes a class name from a given element or collection of elements. + * @method removeClass + * @param {String | HTMLElement | Array} el The element or collection to remove the class from + * @param {String} className the class name to remove from the class attribute + * @return {Boolean | Array} A pass/fail boolean or array of booleans + */ + removeClass: function(el, className) { + return Y.Dom.batch(el, Y.Dom._removeClass, className); + }, + + _removeClass: function(el, className) { + var ret = false, + current, + newClass, + attr; + + if (el && className) { + current = Y.Dom._getAttribute(el, CLASS_NAME) || EMPTY; + Y.Dom.setAttribute(el, CLASS_NAME, current.replace(Y.Dom._getClassRegex(className), EMPTY)); + + newClass = Y.Dom._getAttribute(el, CLASS_NAME); + if (current !== newClass) { // else nothing changed + Y.Dom.setAttribute(el, CLASS_NAME, trim(newClass)); // trim after comparing to current class + ret = true; + + if (Y.Dom._getAttribute(el, CLASS_NAME) === '') { // remove class attribute if empty + attr = (el.hasAttribute && el.hasAttribute(_CLASS)) ? _CLASS : CLASS_NAME; + YAHOO.log('removeClass removing empty class attribute', 'info', 'Dom'); + el.removeAttribute(attr); + } + } + + } else { + YAHOO.log('removeClass called with invalid arguments', 'warn', 'Dom'); + } + + return ret; + }, + + /** + * Replace a class with another class for a given element or collection of elements. + * If no oldClassName is present, the newClassName is simply added. + * @method replaceClass + * @param {String | HTMLElement | Array} el The element or collection to remove the class from + * @param {String} oldClassName the class name to be replaced + * @param {String} newClassName the class name that will be replacing the old class name + * @return {Boolean | Array} A pass/fail boolean or array of booleans + */ + replaceClass: function(el, oldClassName, newClassName) { + return Y.Dom.batch(el, Y.Dom._replaceClass, { from: oldClassName, to: newClassName }); + }, + + _replaceClass: function(el, classObj) { + var className, + from, + to, + ret = false, + current; + + if (el && classObj) { + from = classObj.from; + to = classObj.to; + + if (!to) { + ret = false; + } else if (!from) { // just add if no "from" + ret = Y.Dom._addClass(el, classObj.to); + } else if (from !== to) { // else nothing to replace + // May need to lead with DBLSPACE? + current = Y.Dom._getAttribute(el, CLASS_NAME) || EMPTY; + className = (SPACE + current.replace(Y.Dom._getClassRegex(from), SPACE + to). + replace(/\s+/g, SPACE)). // normalize white space + split(Y.Dom._getClassRegex(to)); + + // insert to into what would have been the first occurrence slot + className.splice(1, 0, SPACE + to); + Y.Dom.setAttribute(el, CLASS_NAME, trim(className.join(EMPTY))); + ret = true; + } + } else { + YAHOO.log('replaceClass called with invalid arguments', 'warn', 'Dom'); + } + + return ret; + }, + + /** + * Returns an ID and applies it to the element "el", if provided. + * @method generateId + * @param {String | HTMLElement | Array} el (optional) An optional element array of elements to add an ID to (no ID is added if one is already present). + * @param {String} prefix (optional) an optional prefix to use (defaults to "yui-gen"). + * @return {String | Array} The generated ID, or array of generated IDs (or original ID if already present on an element) + */ + generateId: function(el, prefix) { + prefix = prefix || 'yui-gen'; + + var f = function(el) { + if (el && el.id) { // do not override existing ID + YAHOO.log('generateId returning existing id ' + el.id, 'info', 'Dom'); + return el.id; + } + + var id = prefix + YAHOO.env._id_counter++; + YAHOO.log('generateId generating ' + id, 'info', 'Dom'); + + if (el) { + if (el[OWNER_DOCUMENT] && el[OWNER_DOCUMENT].getElementById(id)) { // in case one already exists + // use failed id plus prefix to help ensure uniqueness + return Y.Dom.generateId(el, id + prefix); + } + el.id = id; + } + + return id; + }; + + // batch fails when no element, so just generate and return single ID + return Y.Dom.batch(el, f, Y.Dom, true) || f.apply(Y.Dom, arguments); + }, + + /** + * Determines whether an HTMLElement is an ancestor of another HTML element in the DOM hierarchy. + * @method isAncestor + * @param {String | HTMLElement} haystack The possible ancestor + * @param {String | HTMLElement} needle The possible descendent + * @return {Boolean} Whether or not the haystack is an ancestor of needle + */ + isAncestor: function(haystack, needle) { + haystack = Y.Dom.get(haystack); + needle = Y.Dom.get(needle); + + var ret = false; + + if ( (haystack && needle) && (haystack[NODE_TYPE] && needle[NODE_TYPE]) ) { + if (haystack.contains && haystack !== needle) { // contains returns true when equal + ret = haystack.contains(needle); + } + else if (haystack.compareDocumentPosition) { // gecko + ret = !!(haystack.compareDocumentPosition(needle) & 16); + } + } else { + YAHOO.log('isAncestor failed; invalid input: ' + haystack + ',' + needle, 'error', 'Dom'); + } + YAHOO.log('isAncestor(' + haystack + ',' + needle + ' returning ' + ret, 'info', 'Dom'); + return ret; + }, + + /** + * Determines whether an HTMLElement is present in the current document. + * @method inDocument + * @param {String | HTMLElement} el The element to search for + * @param {Object} doc An optional document to search, defaults to element's owner document + * @return {Boolean} Whether or not the element is present in the current document + */ + inDocument: function(el, doc) { + return Y.Dom._inDoc(Y.Dom.get(el), doc); + }, + + _inDoc: function(el, doc) { + var ret = false; + if (el && el[TAG_NAME]) { + doc = doc || el[OWNER_DOCUMENT]; + ret = Y.Dom.isAncestor(doc[DOCUMENT_ELEMENT], el); + } else { + YAHOO.log('inDocument failed: invalid input', 'error', 'Dom'); + } + return ret; + }, + + /** + * Returns an array of HTMLElements that pass the test applied by supplied boolean method. + * For optimized performance, include a tag and/or root node when possible. + * Note: This method operates against a live collection, so modifying the + * collection in the callback (removing/appending nodes, etc.) will have + * side effects. Instead you should iterate the returned nodes array, + * as you would with the native "getElementsByTagName" method. + * @method getElementsBy + * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. + * @param {String} tag (optional) The tag name of the elements being collected + * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point + * @param {Function} apply (optional) A function to apply to each element when found + * @param {Any} o (optional) An optional arg that is passed to the supplied method + * @param {Boolean} overrides (optional) Whether or not to override the scope of "method" with "o" + * @return {Array} Array of HTMLElements + */ + getElementsBy: function(method, tag, root, apply, o, overrides, firstOnly) { + tag = tag || '*'; + root = (root) ? Y.Dom.get(root) : null || document; + + var ret = (firstOnly) ? null : [], + elements; + + // in case Dom.get() returns null + if (root) { + elements = root.getElementsByTagName(tag); + for (var i = 0, len = elements.length; i < len; ++i) { + if ( method(elements[i]) ) { + if (firstOnly) { + ret = elements[i]; + break; + } else { + ret[ret.length] = elements[i]; + } + } + } + + if (apply) { + Y.Dom.batch(ret, apply, o, overrides); + } + } + + YAHOO.log('getElementsBy returning ' + ret, 'info', 'Dom'); + + return ret; + }, + + /** + * Returns the first HTMLElement that passes the test applied by the supplied boolean method. + * @method getElementBy + * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. + * @param {String} tag (optional) The tag name of the elements being collected + * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point + * @return {HTMLElement} + */ + getElementBy: function(method, tag, root) { + return Y.Dom.getElementsBy(method, tag, root, null, null, null, true); + }, + + /** + * Runs the supplied method against each item in the Collection/Array. + * The method is called with the element(s) as the first arg, and the optional param as the second ( method(el, o) ). + * @method batch + * @param {String | HTMLElement | Array} el (optional) An element or array of elements to apply the method to + * @param {Function} method The method to apply to the element(s) + * @param {Any} o (optional) An optional arg that is passed to the supplied method + * @param {Boolean} overrides (optional) Whether or not to override the scope of "method" with "o" + * @return {Any | Array} The return value(s) from the supplied method + */ + batch: function(el, method, o, overrides) { + var collection = [], + scope = (overrides) ? o : null; + + el = (el && (el[TAG_NAME] || el.item)) ? el : Y.Dom.get(el); // skip get() when possible + if (el && method) { + if (el[TAG_NAME] || el.length === undefined) { // element or not array-like + return method.call(scope, el, o); + } + + for (var i = 0; i < el.length; ++i) { + collection[collection.length] = method.call(scope || el[i], el[i], o); + } + } else { + YAHOO.log('batch called with invalid arguments', 'warn', 'Dom'); + return false; + } + return collection; + }, + + /** + * Returns the height of the document. + * @method getDocumentHeight + * @return {Int} The height of the actual document (which includes the body and its margin). + */ + getDocumentHeight: function() { + var scrollHeight = (document[COMPAT_MODE] != CSS1_COMPAT || isSafari) ? document.body.scrollHeight : documentElement.scrollHeight, + h = Math.max(scrollHeight, Y.Dom.getViewportHeight()); + + YAHOO.log('getDocumentHeight returning ' + h, 'info', 'Dom'); + return h; + }, + + /** + * Returns the width of the document. + * @method getDocumentWidth + * @return {Int} The width of the actual document (which includes the body and its margin). + */ + getDocumentWidth: function() { + var scrollWidth = (document[COMPAT_MODE] != CSS1_COMPAT || isSafari) ? document.body.scrollWidth : documentElement.scrollWidth, + w = Math.max(scrollWidth, Y.Dom.getViewportWidth()); + YAHOO.log('getDocumentWidth returning ' + w, 'info', 'Dom'); + return w; + }, + + /** + * Returns the current height of the viewport. + * @method getViewportHeight + * @return {Int} The height of the viewable area of the page (excludes scrollbars). + */ + getViewportHeight: function() { + var height = self.innerHeight, // Safari, Opera + mode = document[COMPAT_MODE]; + + if ( (mode || isIE) && !isOpera ) { // IE, Gecko + height = (mode == CSS1_COMPAT) ? + documentElement.clientHeight : // Standards + document.body.clientHeight; // Quirks + } + + YAHOO.log('getViewportHeight returning ' + height, 'info', 'Dom'); + return height; + }, + + /** + * Returns the current width of the viewport. + * @method getViewportWidth + * @return {Int} The width of the viewable area of the page (excludes scrollbars). + */ + + getViewportWidth: function() { + var width = self.innerWidth, // Safari + mode = document[COMPAT_MODE]; + + if (mode || isIE) { // IE, Gecko, Opera + width = (mode == CSS1_COMPAT) ? + documentElement.clientWidth : // Standards + document.body.clientWidth; // Quirks + } + YAHOO.log('getViewportWidth returning ' + width, 'info', 'Dom'); + return width; + }, + + /** + * Returns the nearest ancestor that passes the test applied by supplied boolean method. + * For performance reasons, IDs are not accepted and argument validation omitted. + * @method getAncestorBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. + * @return {Object} HTMLElement or null if not found + */ + getAncestorBy: function(node, method) { + while ( (node = node[PARENT_NODE]) ) { // NOTE: assignment + if ( Y.Dom._testElement(node, method) ) { + YAHOO.log('getAncestorBy returning ' + node, 'info', 'Dom'); + return node; + } + } + + YAHOO.log('getAncestorBy returning null (no ancestor passed test)', 'error', 'Dom'); + return null; + }, + + /** + * Returns the nearest ancestor with the given className. + * @method getAncestorByClassName + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @param {String} className + * @return {Object} HTMLElement + */ + getAncestorByClassName: function(node, className) { + node = Y.Dom.get(node); + if (!node) { + YAHOO.log('getAncestorByClassName failed: invalid node argument', 'error', 'Dom'); + return null; + } + var method = function(el) { return Y.Dom.hasClass(el, className); }; + return Y.Dom.getAncestorBy(node, method); + }, + + /** + * Returns the nearest ancestor with the given tagName. + * @method getAncestorByTagName + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @param {String} tagName + * @return {Object} HTMLElement + */ + getAncestorByTagName: function(node, tagName) { + node = Y.Dom.get(node); + if (!node) { + YAHOO.log('getAncestorByTagName failed: invalid node argument', 'error', 'Dom'); + return null; + } + var method = function(el) { + return el[TAG_NAME] && el[TAG_NAME].toUpperCase() == tagName.toUpperCase(); + }; + + return Y.Dom.getAncestorBy(node, method); + }, + + /** + * Returns the previous sibling that is an HTMLElement. + * For performance reasons, IDs are not accepted and argument validation omitted. + * Returns the nearest HTMLElement sibling if no method provided. + * @method getPreviousSiblingBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test siblings + * that receives the sibling node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getPreviousSiblingBy: function(node, method) { + while (node) { + node = node.previousSibling; + if ( Y.Dom._testElement(node, method) ) { + return node; + } + } + return null; + }, + + /** + * Returns the previous sibling that is an HTMLElement + * @method getPreviousSibling + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getPreviousSibling: function(node) { + node = Y.Dom.get(node); + if (!node) { + YAHOO.log('getPreviousSibling failed: invalid node argument', 'error', 'Dom'); + return null; + } + + return Y.Dom.getPreviousSiblingBy(node); + }, + + /** + * Returns the next HTMLElement sibling that passes the boolean method. + * For performance reasons, IDs are not accepted and argument validation omitted. + * Returns the nearest HTMLElement sibling if no method provided. + * @method getNextSiblingBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test siblings + * that receives the sibling node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getNextSiblingBy: function(node, method) { + while (node) { + node = node.nextSibling; + if ( Y.Dom._testElement(node, method) ) { + return node; + } + } + return null; + }, + + /** + * Returns the next sibling that is an HTMLElement + * @method getNextSibling + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getNextSibling: function(node) { + node = Y.Dom.get(node); + if (!node) { + YAHOO.log('getNextSibling failed: invalid node argument', 'error', 'Dom'); + return null; + } + + return Y.Dom.getNextSiblingBy(node); + }, + + /** + * Returns the first HTMLElement child that passes the test method. + * @method getFirstChildBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test children + * that receives the node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getFirstChildBy: function(node, method) { + var child = ( Y.Dom._testElement(node.firstChild, method) ) ? node.firstChild : null; + return child || Y.Dom.getNextSiblingBy(node.firstChild, method); + }, + + /** + * Returns the first HTMLElement child. + * @method getFirstChild + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getFirstChild: function(node, method) { + node = Y.Dom.get(node); + if (!node) { + YAHOO.log('getFirstChild failed: invalid node argument', 'error', 'Dom'); + return null; + } + return Y.Dom.getFirstChildBy(node); + }, + + /** + * Returns the last HTMLElement child that passes the test method. + * @method getLastChildBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test children + * that receives the node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getLastChildBy: function(node, method) { + if (!node) { + YAHOO.log('getLastChild failed: invalid node argument', 'error', 'Dom'); + return null; + } + var child = ( Y.Dom._testElement(node.lastChild, method) ) ? node.lastChild : null; + return child || Y.Dom.getPreviousSiblingBy(node.lastChild, method); + }, + + /** + * Returns the last HTMLElement child. + * @method getLastChild + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getLastChild: function(node) { + node = Y.Dom.get(node); + return Y.Dom.getLastChildBy(node); + }, + + /** + * Returns an array of HTMLElement childNodes that pass the test method. + * @method getChildrenBy + * @param {HTMLElement} node The HTMLElement to start from + * @param {Function} method A boolean function used to test children + * that receives the node being tested as its only argument + * @return {Array} A static array of HTMLElements + */ + getChildrenBy: function(node, method) { + var child = Y.Dom.getFirstChildBy(node, method), + children = child ? [child] : []; + + Y.Dom.getNextSiblingBy(child, function(node) { + if ( !method || method(node) ) { + children[children.length] = node; + } + return false; // fail test to collect all children + }); + + return children; + }, + + /** + * Returns an array of HTMLElement childNodes. + * @method getChildren + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Array} A static array of HTMLElements + */ + getChildren: function(node) { + node = Y.Dom.get(node); + if (!node) { + YAHOO.log('getChildren failed: invalid node argument', 'error', 'Dom'); + } + + return Y.Dom.getChildrenBy(node); + }, + + /** + * Returns the left scroll value of the document + * @method getDocumentScrollLeft + * @param {HTMLDocument} document (optional) The document to get the scroll value of + * @return {Int} The amount that the document is scrolled to the left + */ + getDocumentScrollLeft: function(doc) { + doc = doc || document; + return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft); + }, + + /** + * Returns the top scroll value of the document + * @method getDocumentScrollTop + * @param {HTMLDocument} document (optional) The document to get the scroll value of + * @return {Int} The amount that the document is scrolled to the top + */ + getDocumentScrollTop: function(doc) { + doc = doc || document; + return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop); + }, + + /** + * Inserts the new node as the previous sibling of the reference node + * @method insertBefore + * @param {String | HTMLElement} newNode The node to be inserted + * @param {String | HTMLElement} referenceNode The node to insert the new node before + * @return {HTMLElement} The node that was inserted (or null if insert fails) + */ + insertBefore: function(newNode, referenceNode) { + newNode = Y.Dom.get(newNode); + referenceNode = Y.Dom.get(referenceNode); + + if (!newNode || !referenceNode || !referenceNode[PARENT_NODE]) { + YAHOO.log('insertAfter failed: missing or invalid arg(s)', 'error', 'Dom'); + return null; + } + + return referenceNode[PARENT_NODE].insertBefore(newNode, referenceNode); + }, + + /** + * Inserts the new node as the next sibling of the reference node + * @method insertAfter + * @param {String | HTMLElement} newNode The node to be inserted + * @param {String | HTMLElement} referenceNode The node to insert the new node after + * @return {HTMLElement} The node that was inserted (or null if insert fails) + */ + insertAfter: function(newNode, referenceNode) { + newNode = Y.Dom.get(newNode); + referenceNode = Y.Dom.get(referenceNode); + + if (!newNode || !referenceNode || !referenceNode[PARENT_NODE]) { + YAHOO.log('insertAfter failed: missing or invalid arg(s)', 'error', 'Dom'); + return null; + } + + if (referenceNode.nextSibling) { + return referenceNode[PARENT_NODE].insertBefore(newNode, referenceNode.nextSibling); + } else { + return referenceNode[PARENT_NODE].appendChild(newNode); + } + }, + + /** + * Creates a Region based on the viewport relative to the document. + * @method getClientRegion + * @return {Region} A Region object representing the viewport which accounts for document scroll + */ + getClientRegion: function() { + var t = Y.Dom.getDocumentScrollTop(), + l = Y.Dom.getDocumentScrollLeft(), + r = Y.Dom.getViewportWidth() + l, + b = Y.Dom.getViewportHeight() + t; + + return new Y.Region(t, r, b, l); + }, + + /** + * Provides a normalized attribute interface. + * @method setAttribute + * @param {String | HTMLElement} el The target element for the attribute. + * @param {String} attr The attribute to set. + * @param {String} val The value of the attribute. + */ + setAttribute: function(el, attr, val) { + Y.Dom.batch(el, Y.Dom._setAttribute, { attr: attr, val: val }); + }, + + _setAttribute: function(el, args) { + var attr = Y.Dom._toCamel(args.attr), + val = args.val; + + if (el && el.setAttribute) { + // set as DOM property, except for BUTTON, which errors on property setter + if (Y.Dom.DOT_ATTRIBUTES[attr] && el.tagName && el.tagName != 'BUTTON') { + el[attr] = val; + } else { + attr = Y.Dom.CUSTOM_ATTRIBUTES[attr] || attr; + el.setAttribute(attr, val); + } + } else { + YAHOO.log('setAttribute method not available for ' + el, 'error', 'Dom'); + } + }, + + /** + * Provides a normalized attribute interface. + * @method getAttribute + * @param {String | HTMLElement} el The target element for the attribute. + * @param {String} attr The attribute to get. + * @return {String} The current value of the attribute. + */ + getAttribute: function(el, attr) { + return Y.Dom.batch(el, Y.Dom._getAttribute, attr); + }, + + + _getAttribute: function(el, attr) { + var val; + attr = Y.Dom.CUSTOM_ATTRIBUTES[attr] || attr; + + if (Y.Dom.DOT_ATTRIBUTES[attr]) { + val = el[attr]; + } else if (el && 'getAttribute' in el) { + if (/^(?:href|src)$/.test(attr)) { // use IE flag to return exact value + val = el.getAttribute(attr, 2); + } else { + val = el.getAttribute(attr); + } + } else { + YAHOO.log('getAttribute method not available for ' + el, 'error', 'Dom'); + } + + return val; + }, + + _toCamel: function(property) { + var c = propertyCache; + + function tU(x,l) { + return l.toUpperCase(); + } + + return c[property] || (c[property] = property.indexOf('-') === -1 ? + property : + property.replace( /-([a-z])/gi, tU )); + }, + + _getClassRegex: function(className) { + var re; + if (className !== undefined) { // allow empty string to pass + if (className.exec) { // already a RegExp + re = className; + } else { + re = reCache[className]; + if (!re) { + // escape special chars (".", "[", etc.) + className = className.replace(Y.Dom._patterns.CLASS_RE_TOKENS, '\\$1'); + className = className.replace(/\s+/g, SPACE); // convert line breaks and other delims + re = reCache[className] = new RegExp(C_START + className + C_END, G); + } + } + } + return re; + }, + + _patterns: { + ROOT_TAG: /^body|html$/i, // body for quirks mode, html for standards, + CLASS_RE_TOKENS: /([\.\(\)\^\$\*\+\?\|\[\]\{\}\\])/g + }, + + + _testElement: function(node, method) { + return node && node[NODE_TYPE] == 1 && ( !method || method(node) ); + }, + + _calcBorders: function(node, xy2) { + var t = parseInt(Y.Dom[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0, + l = parseInt(Y.Dom[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0; + if (isGecko) { + if (RE_TABLE.test(node[TAG_NAME])) { + t = 0; + l = 0; + } + } + xy2[0] += l; + xy2[1] += t; + return xy2; + } + }; + + var _getComputedStyle = Y.Dom[GET_COMPUTED_STYLE]; + // fix opera computedStyle default color unit (convert to rgb) + if (UA.opera) { + Y.Dom[GET_COMPUTED_STYLE] = function(node, att) { + var val = _getComputedStyle(node, att); + if (RE_COLOR.test(att)) { + val = Y.Dom.Color.toRGB(val); + } + + return val; + }; + + } + + // safari converts transparent to rgba(), others use "transparent" + if (UA.webkit) { + Y.Dom[GET_COMPUTED_STYLE] = function(node, att) { + var val = _getComputedStyle(node, att); + + if (val === 'rgba(0, 0, 0, 0)') { + val = 'transparent'; + } + + return val; + }; + + } + + if (UA.ie && UA.ie >= 8) { + Y.Dom.DOT_ATTRIBUTES.type = true; // IE 8 errors on input.setAttribute('type') + } +})(); +/** + * A region is a representation of an object on a grid. It is defined + * by the top, right, bottom, left extents, so is rectangular by default. If + * other shapes are required, this class could be extended to support it. + * @namespace YAHOO.util + * @class Region + * @param {Int} t the top extent + * @param {Int} r the right extent + * @param {Int} b the bottom extent + * @param {Int} l the left extent + * @constructor + */ +YAHOO.util.Region = function(t, r, b, l) { + + /** + * The region's top extent + * @property top + * @type Int + */ + this.top = t; + + /** + * The region's top extent + * @property y + * @type Int + */ + this.y = t; + + /** + * The region's top extent as index, for symmetry with set/getXY + * @property 1 + * @type Int + */ + this[1] = t; + + /** + * The region's right extent + * @property right + * @type int + */ + this.right = r; + + /** + * The region's bottom extent + * @property bottom + * @type Int + */ + this.bottom = b; + + /** + * The region's left extent + * @property left + * @type Int + */ + this.left = l; + + /** + * The region's left extent + * @property x + * @type Int + */ + this.x = l; + + /** + * The region's left extent as index, for symmetry with set/getXY + * @property 0 + * @type Int + */ + this[0] = l; + + /** + * The region's total width + * @property width + * @type Int + */ + this.width = this.right - this.left; + + /** + * The region's total height + * @property height + * @type Int + */ + this.height = this.bottom - this.top; +}; + +/** + * Returns true if this region contains the region passed in + * @method contains + * @param {Region} region The region to evaluate + * @return {Boolean} True if the region is contained with this region, + * else false + */ +YAHOO.util.Region.prototype.contains = function(region) { + return ( region.left >= this.left && + region.right <= this.right && + region.top >= this.top && + region.bottom <= this.bottom ); + + // this.logger.debug("does " + this + " contain " + region + " ... " + ret); +}; + +/** + * Returns the area of the region + * @method getArea + * @return {Int} the region's area + */ +YAHOO.util.Region.prototype.getArea = function() { + return ( (this.bottom - this.top) * (this.right - this.left) ); +}; + +/** + * Returns the region where the passed in region overlaps with this one + * @method intersect + * @param {Region} region The region that intersects + * @return {Region} The overlap region, or null if there is no overlap + */ +YAHOO.util.Region.prototype.intersect = function(region) { + var t = Math.max( this.top, region.top ), + r = Math.min( this.right, region.right ), + b = Math.min( this.bottom, region.bottom ), + l = Math.max( this.left, region.left ); + + if (b >= t && r >= l) { + return new YAHOO.util.Region(t, r, b, l); + } else { + return null; + } +}; + +/** + * Returns the region representing the smallest region that can contain both + * the passed in region and this region. + * @method union + * @param {Region} region The region that to create the union with + * @return {Region} The union region + */ +YAHOO.util.Region.prototype.union = function(region) { + var t = Math.min( this.top, region.top ), + r = Math.max( this.right, region.right ), + b = Math.max( this.bottom, region.bottom ), + l = Math.min( this.left, region.left ); + + return new YAHOO.util.Region(t, r, b, l); +}; + +/** + * toString + * @method toString + * @return string the region properties + */ +YAHOO.util.Region.prototype.toString = function() { + return ( "Region {" + + "top: " + this.top + + ", right: " + this.right + + ", bottom: " + this.bottom + + ", left: " + this.left + + ", height: " + this.height + + ", width: " + this.width + + "}" ); +}; + +/** + * Returns a region that is occupied by the DOM element + * @method getRegion + * @param {HTMLElement} el The element + * @return {Region} The region that the element occupies + * @static + */ +YAHOO.util.Region.getRegion = function(el) { + var p = YAHOO.util.Dom.getXY(el), + t = p[1], + r = p[0] + el.offsetWidth, + b = p[1] + el.offsetHeight, + l = p[0]; + + return new YAHOO.util.Region(t, r, b, l); +}; + +///////////////////////////////////////////////////////////////////////////// + + +/** + * A point is a region that is special in that it represents a single point on + * the grid. + * @namespace YAHOO.util + * @class Point + * @param {Int} x The X position of the point + * @param {Int} y The Y position of the point + * @constructor + * @extends YAHOO.util.Region + */ +YAHOO.util.Point = function(x, y) { + if (YAHOO.lang.isArray(x)) { // accept input from Dom.getXY, Event.getXY, etc. + y = x[1]; // dont blow away x yet + x = x[0]; + } + + YAHOO.util.Point.superclass.constructor.call(this, y, x, y, x); +}; + +YAHOO.extend(YAHOO.util.Point, YAHOO.util.Region); + +(function() { +/** + * Internal methods used to add style management functionality to DOM. + * @module dom + * @class IEStyle + * @namespace YAHOO.util.Dom + */ + +var Y = YAHOO.util, + CLIENT_TOP = 'clientTop', + CLIENT_LEFT = 'clientLeft', + PARENT_NODE = 'parentNode', + RIGHT = 'right', + HAS_LAYOUT = 'hasLayout', + PX = 'px', + OPACITY = 'opacity', + AUTO = 'auto', + BORDER_LEFT_WIDTH = 'borderLeftWidth', + BORDER_TOP_WIDTH = 'borderTopWidth', + BORDER_RIGHT_WIDTH = 'borderRightWidth', + BORDER_BOTTOM_WIDTH = 'borderBottomWidth', + VISIBLE = 'visible', + TRANSPARENT = 'transparent', + HEIGHT = 'height', + WIDTH = 'width', + STYLE = 'style', + CURRENT_STYLE = 'currentStyle', + +// IE getComputedStyle +// TODO: unit-less lineHeight (e.g. 1.22) + re_size = /^width|height$/, + re_unit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i, + + ComputedStyle = { + /** + * @method get + * @description Method used by DOM to get style information for IE + * @param {HTMLElement} el The element to check + * @param {String} property The property to check + * @returns {String} The computed style + */ + get: function(el, property) { + var value = '', + current = el[CURRENT_STYLE][property]; + + if (property === OPACITY) { + value = Y.Dom.getStyle(el, OPACITY); + } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert + value = current; + } else if (Y.Dom.IE_COMPUTED[property]) { // use compute function + value = Y.Dom.IE_COMPUTED[property](el, property); + } else if (re_unit.test(current)) { // convert to pixel + value = Y.Dom.IE.ComputedStyle.getPixel(el, property); + } else { + value = current; + } + + return value; + }, + /** + * @method getOffset + * @description Determine the offset of an element + * @param {HTMLElement} el The element to check + * @param {String} prop The property to check. + * @return {String} The offset + */ + getOffset: function(el, prop) { + var current = el[CURRENT_STYLE][prop], // value of "width", "top", etc. + capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc. + offset = 'offset' + capped, // "offsetWidth", "offsetTop", etc. + pixel = 'pixel' + capped, // "pixelWidth", "pixelTop", etc. + value = '', + actual; + + if (current == AUTO) { + actual = el[offset]; // offsetHeight/Top etc. + if (actual === undefined) { // likely "right" or "bottom" + value = 0; + } + + value = actual; + if (re_size.test(prop)) { // account for box model diff + el[STYLE][prop] = actual; + if (el[offset] > actual) { + // the difference is padding + border (works in Standards & Quirks modes) + value = actual - (el[offset] - actual); + } + el[STYLE][prop] = AUTO; // revert to auto + } + } else { // convert units to px + if (!el[STYLE][pixel] && !el[STYLE][prop]) { // need to map style.width to currentStyle (no currentStyle.pixelWidth) + el[STYLE][prop] = current; // no style.pixelWidth if no style.width + } + value = el[STYLE][pixel]; + } + return value + PX; + }, + /** + * @method getBorderWidth + * @description Try to determine the width of an elements border + * @param {HTMLElement} el The element to check + * @param {String} property The property to check + * @return {String} The elements border width + */ + getBorderWidth: function(el, property) { + // clientHeight/Width = paddingBox (e.g. offsetWidth - borderWidth) + // clientTop/Left = borderWidth + var value = null; + if (!el[CURRENT_STYLE][HAS_LAYOUT]) { // TODO: unset layout? + el[STYLE].zoom = 1; // need layout to measure client + } + + switch(property) { + case BORDER_TOP_WIDTH: + value = el[CLIENT_TOP]; + break; + case BORDER_BOTTOM_WIDTH: + value = el.offsetHeight - el.clientHeight - el[CLIENT_TOP]; + break; + case BORDER_LEFT_WIDTH: + value = el[CLIENT_LEFT]; + break; + case BORDER_RIGHT_WIDTH: + value = el.offsetWidth - el.clientWidth - el[CLIENT_LEFT]; + break; + } + return value + PX; + }, + /** + * @method getPixel + * @description Get the pixel value from a style property + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The pixel value + */ + getPixel: function(node, att) { + // use pixelRight to convert to px + var val = null, + styleRight = node[CURRENT_STYLE][RIGHT], + current = node[CURRENT_STYLE][att]; + + node[STYLE][RIGHT] = current; + val = node[STYLE].pixelRight; + node[STYLE][RIGHT] = styleRight; // revert + + return val + PX; + }, + + /** + * @method getMargin + * @description Get the margin value from a style property + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The margin value + */ + getMargin: function(node, att) { + var val; + if (node[CURRENT_STYLE][att] == AUTO) { + val = 0 + PX; + } else { + val = Y.Dom.IE.ComputedStyle.getPixel(node, att); + } + return val; + }, + + /** + * @method getVisibility + * @description Get the visibility of an element + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The value + */ + getVisibility: function(node, att) { + var current; + while ( (current = node[CURRENT_STYLE]) && current[att] == 'inherit') { // NOTE: assignment in test + node = node[PARENT_NODE]; + } + return (current) ? current[att] : VISIBLE; + }, + + /** + * @method getColor + * @description Get the color of an element + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The value + */ + getColor: function(node, att) { + return Y.Dom.Color.toRGB(node[CURRENT_STYLE][att]) || TRANSPARENT; + }, + + /** + * @method getBorderColor + * @description Get the bordercolor of an element + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The value + */ + getBorderColor: function(node, att) { + var current = node[CURRENT_STYLE], + val = current[att] || current.color; + return Y.Dom.Color.toRGB(Y.Dom.Color.toHex(val)); + } + + }, + +//fontSize: getPixelFont, + IEComputed = {}; + +IEComputed.top = IEComputed.right = IEComputed.bottom = IEComputed.left = + IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset; + +IEComputed.color = ComputedStyle.getColor; + +IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] = + IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] = + ComputedStyle.getBorderWidth; + +IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom = + IEComputed.marginLeft = ComputedStyle.getMargin; + +IEComputed.visibility = ComputedStyle.getVisibility; +IEComputed.borderColor = IEComputed.borderTopColor = + IEComputed.borderRightColor = IEComputed.borderBottomColor = + IEComputed.borderLeftColor = ComputedStyle.getBorderColor; + +Y.Dom.IE_COMPUTED = IEComputed; +Y.Dom.IE_ComputedStyle = ComputedStyle; +})(); +(function() { +/** + * Add style management functionality to DOM. + * @module dom + * @class Color + * @namespace YAHOO.util.Dom + */ + +var TO_STRING = 'toString', + PARSE_INT = parseInt, + RE = RegExp, + Y = YAHOO.util; + +Y.Dom.Color = { + /** + * @property KEYWORDS + * @type Object + * @description Color keywords used when converting to Hex + */ + KEYWORDS: { + black: '000', + silver: 'c0c0c0', + gray: '808080', + white: 'fff', + maroon: '800000', + red: 'f00', + purple: '800080', + fuchsia: 'f0f', + green: '008000', + lime: '0f0', + olive: '808000', + yellow: 'ff0', + navy: '000080', + blue: '00f', + teal: '008080', + aqua: '0ff' + }, + /** + * @property re_RGB + * @private + * @type Regex + * @description Regex to parse rgb(0,0,0) formatted strings + */ + re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i, + /** + * @property re_hex + * @private + * @type Regex + * @description Regex to parse #123456 formatted strings + */ + re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i, + /** + * @property re_hex3 + * @private + * @type Regex + * @description Regex to parse #123 formatted strings + */ + re_hex3: /([0-9A-F])/gi, + /** + * @method toRGB + * @description Converts a hex or color string to an rgb string: rgb(0,0,0) + * @param {String} val The string to convert to RGB notation. + * @returns {String} The converted string + */ + toRGB: function(val) { + if (!Y.Dom.Color.re_RGB.test(val)) { + val = Y.Dom.Color.toHex(val); + } + + if(Y.Dom.Color.re_hex.exec(val)) { + val = 'rgb(' + [ + PARSE_INT(RE.$1, 16), + PARSE_INT(RE.$2, 16), + PARSE_INT(RE.$3, 16) + ].join(', ') + ')'; + } + return val; + }, + /** + * @method toHex + * @description Converts an rgb or color string to a hex string: #123456 + * @param {String} val The string to convert to hex notation. + * @returns {String} The converted string + */ + toHex: function(val) { + val = Y.Dom.Color.KEYWORDS[val] || val; + if (Y.Dom.Color.re_RGB.exec(val)) { + val = [ + Number(RE.$1).toString(16), + Number(RE.$2).toString(16), + Number(RE.$3).toString(16) + ]; + + for (var i = 0; i < val.length; i++) { + if (val[i].length < 2) { + val[i] = '0' + val[i]; + } + } + + val = val.join(''); + } + + if (val.length < 6) { + val = val.replace(Y.Dom.Color.re_hex3, '$1$1'); + } + + if (val !== 'transparent' && val.indexOf('#') < 0) { + val = '#' + val; + } + + return val.toUpperCase(); + } +}; +}()); +YAHOO.register("dom", YAHOO.util.Dom, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-min.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-min.js new file mode 100644 index 0000000..194f1e8 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-min.js @@ -0,0 +1,9 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +(function(){YAHOO.env._id_counter=YAHOO.env._id_counter||0;var e=YAHOO.util,k=YAHOO.lang,L=YAHOO.env.ua,a=YAHOO.lang.trim,B={},F={},m=/^t(?:able|d|h)$/i,w=/color$/i,j=window.document,v=j.documentElement,C="ownerDocument",M="defaultView",U="documentElement",S="compatMode",z="offsetLeft",o="offsetTop",T="offsetParent",x="parentNode",K="nodeType",c="tagName",n="scrollLeft",H="scrollTop",p="getBoundingClientRect",V="getComputedStyle",y="currentStyle",l="CSS1Compat",A="BackCompat",E="class",f="className",i="",b=" ",R="(?:^|\\s)",J="(?= |$)",t="g",O="position",D="fixed",u="relative",I="left",N="top",Q="medium",P="borderLeftWidth",q="borderTopWidth",d=L.opera,h=L.webkit,g=L.gecko,s=L.ie;e.Dom={CUSTOM_ATTRIBUTES:(!v.hasAttribute)?{"for":"htmlFor","class":f}:{"htmlFor":"for","className":E},DOT_ATTRIBUTES:{checked:true},get:function(aa){var ac,X,ab,Z,W,G,Y=null;if(aa){if(typeof aa=="string"||typeof aa=="number"){ac=aa+"";aa=j.getElementById(aa);G=(aa)?aa.attributes:null;if(aa&&G&&G.id&&G.id.value===ac){return aa;}else{if(aa&&j.all){aa=null;X=j.all[ac];if(X&&X.length){for(Z=0,W=X.length;Z-1;}}else{}return G;},addClass:function(W,G){return e.Dom.batch(W,e.Dom._addClass,G);},_addClass:function(X,W){var G=false,Y;if(X&&W){Y=e.Dom._getAttribute(X,f)||i;if(!e.Dom._hasClass(X,W)){e.Dom.setAttribute(X,f,a(Y+b+W));G=true;}}else{}return G;},removeClass:function(W,G){return e.Dom.batch(W,e.Dom._removeClass,G);},_removeClass:function(Y,X){var W=false,aa,Z,G;if(Y&&X){aa=e.Dom._getAttribute(Y,f)||i;e.Dom.setAttribute(Y,f,aa.replace(e.Dom._getClassRegex(X),i));Z=e.Dom._getAttribute(Y,f);if(aa!==Z){e.Dom.setAttribute(Y,f,a(Z));W=true;if(e.Dom._getAttribute(Y,f)===""){G=(Y.hasAttribute&&Y.hasAttribute(E))?E:f;Y.removeAttribute(G);}}}else{}return W;},replaceClass:function(X,W,G){return e.Dom.batch(X,e.Dom._replaceClass,{from:W,to:G});},_replaceClass:function(Y,X){var W,ab,aa,G=false,Z;if(Y&&X){ab=X.from;aa=X.to;if(!aa){G=false;}else{if(!ab){G=e.Dom._addClass(Y,X.to);}else{if(ab!==aa){Z=e.Dom._getAttribute(Y,f)||i;W=(b+Z.replace(e.Dom._getClassRegex(ab),b+aa).replace(/\s+/g,b)).split(e.Dom._getClassRegex(aa));W.splice(1,0,b+aa);e.Dom.setAttribute(Y,f,a(W.join(i)));G=true;}}}}else{}return G;},generateId:function(G,X){X=X||"yui-gen";var W=function(Y){if(Y&&Y.id){return Y.id;}var Z=X+YAHOO.env._id_counter++; +if(Y){if(Y[C]&&Y[C].getElementById(Z)){return e.Dom.generateId(Y,Z+X);}Y.id=Z;}return Z;};return e.Dom.batch(G,W,e.Dom,true)||W.apply(e.Dom,arguments);},isAncestor:function(W,X){W=e.Dom.get(W);X=e.Dom.get(X);var G=false;if((W&&X)&&(W[K]&&X[K])){if(W.contains&&W!==X){G=W.contains(X);}else{if(W.compareDocumentPosition){G=!!(W.compareDocumentPosition(X)&16);}}}else{}return G;},inDocument:function(G,W){return e.Dom._inDoc(e.Dom.get(G),W);},_inDoc:function(W,X){var G=false;if(W&&W[c]){X=X||W[C];G=e.Dom.isAncestor(X[U],W);}else{}return G;},getElementsBy:function(W,af,ab,ad,X,ac,ae){af=af||"*";ab=(ab)?e.Dom.get(ab):null||j;var aa=(ae)?null:[],G;if(ab){G=ab.getElementsByTagName(af);for(var Y=0,Z=G.length;Y=8){e.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(d,e,a,c){this.top=d;this.y=d;this[1]=d;this.right=e;this.bottom=a;this.left=c;this.x=c;this[0]=c;this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(a){return(a.left>=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(f){var d=Math.max(this.top,f.top),e=Math.min(this.right,f.right),a=Math.min(this.bottom,f.bottom),c=Math.max(this.left,f.left); +if(a>=d&&e>=c){return new YAHOO.util.Region(d,e,a,c);}else{return null;}};YAHOO.util.Region.prototype.union=function(f){var d=Math.min(this.top,f.top),e=Math.max(this.right,f.right),a=Math.max(this.bottom,f.bottom),c=Math.min(this.left,f.left);return new YAHOO.util.Region(d,e,a,c);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(e){var g=YAHOO.util.Dom.getXY(e),d=g[1],f=g[0]+e.offsetWidth,a=g[1]+e.offsetHeight,c=g[0];return new YAHOO.util.Region(d,f,a,c);};YAHOO.util.Point=function(a,b){if(YAHOO.lang.isArray(a)){b=a[1];a=a[0];}YAHOO.util.Point.superclass.constructor.call(this,b,a,b,a);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var b=YAHOO.util,a="clientTop",f="clientLeft",j="parentNode",k="right",w="hasLayout",i="px",u="opacity",l="auto",d="borderLeftWidth",g="borderTopWidth",p="borderRightWidth",v="borderBottomWidth",s="visible",q="transparent",n="height",e="width",h="style",t="currentStyle",r=/^width|height$/,o=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,m={get:function(x,z){var y="",A=x[t][z];if(z===u){y=b.Dom.getStyle(x,u);}else{if(!A||(A.indexOf&&A.indexOf(i)>-1)){y=A;}else{if(b.Dom.IE_COMPUTED[z]){y=b.Dom.IE_COMPUTED[z](x,z);}else{if(o.test(A)){y=b.Dom.IE.ComputedStyle.getPixel(x,z);}else{y=A;}}}}return y;},getOffset:function(z,E){var B=z[t][E],x=E.charAt(0).toUpperCase()+E.substr(1),C="offset"+x,y="pixel"+x,A="",D;if(B==l){D=z[C];if(D===undefined){A=0;}A=D;if(r.test(E)){z[h][E]=D;if(z[C]>D){A=D-(z[C]-D);}z[h][E]=l;}}else{if(!z[h][y]&&!z[h][E]){z[h][E]=B;}A=z[h][y];}return A+i;},getBorderWidth:function(x,z){var y=null;if(!x[t][w]){x[h].zoom=1;}switch(z){case g:y=x[a];break;case v:y=x.offsetHeight-x.clientHeight-x[a];break;case d:y=x[f];break;case p:y=x.offsetWidth-x.clientWidth-x[f];break;}return y+i;},getPixel:function(y,x){var A=null,B=y[t][k],z=y[t][x];y[h][k]=z;A=y[h].pixelRight;y[h][k]=B;return A+i;},getMargin:function(y,x){var z;if(y[t][x]==l){z=0+i;}else{z=b.Dom.IE.ComputedStyle.getPixel(y,x);}return z;},getVisibility:function(y,x){var z;while((z=y[t])&&z[x]=="inherit"){y=y[j];}return(z)?z[x]:s;},getColor:function(y,x){return b.Dom.Color.toRGB(y[t][x])||q;},getBorderColor:function(y,x){var z=y[t],A=z[x]||z.color;return b.Dom.Color.toRGB(b.Dom.Color.toHex(A));}},c={};c.top=c.right=c.bottom=c.left=c[e]=c[n]=m.getOffset;c.color=m.getColor;c[g]=c[p]=c[v]=c[d]=m.getBorderWidth;c.marginTop=c.marginRight=c.marginBottom=c.marginLeft=m.getMargin;c.visibility=m.getVisibility;c.borderColor=c.borderTopColor=c.borderRightColor=c.borderBottomColor=c.borderLeftColor=m.getBorderColor;b.Dom.IE_COMPUTED=c;b.Dom.IE_ComputedStyle=m;})();(function(){var c="toString",a=parseInt,b=RegExp,d=YAHOO.util;d.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(e){if(!d.Dom.Color.re_RGB.test(e)){e=d.Dom.Color.toHex(e);}if(d.Dom.Color.re_hex.exec(e)){e="rgb("+[a(b.$1,16),a(b.$2,16),a(b.$3,16)].join(", ")+")";}return e;},toHex:function(f){f=d.Dom.Color.KEYWORDS[f]||f;if(d.Dom.Color.re_RGB.exec(f)){f=[Number(b.$1).toString(16),Number(b.$2).toString(16),Number(b.$3).toString(16)];for(var e=0;e -1; + } + } else { + } + + return ret; + }, + + /** + * Adds a class name to a given element or collection of elements. + * @method addClass + * @param {String | HTMLElement | Array} el The element or collection to add the class to + * @param {String} className the class name to add to the class attribute + * @return {Boolean | Array} A pass/fail boolean or array of booleans + */ + addClass: function(el, className) { + return Y.Dom.batch(el, Y.Dom._addClass, className); + }, + + _addClass: function(el, className) { + var ret = false, + current; + + if (el && className) { + current = Y.Dom._getAttribute(el, CLASS_NAME) || EMPTY; + if ( !Y.Dom._hasClass(el, className) ) { + Y.Dom.setAttribute(el, CLASS_NAME, trim(current + SPACE + className)); + ret = true; + } + } else { + } + + return ret; + }, + + /** + * Removes a class name from a given element or collection of elements. + * @method removeClass + * @param {String | HTMLElement | Array} el The element or collection to remove the class from + * @param {String} className the class name to remove from the class attribute + * @return {Boolean | Array} A pass/fail boolean or array of booleans + */ + removeClass: function(el, className) { + return Y.Dom.batch(el, Y.Dom._removeClass, className); + }, + + _removeClass: function(el, className) { + var ret = false, + current, + newClass, + attr; + + if (el && className) { + current = Y.Dom._getAttribute(el, CLASS_NAME) || EMPTY; + Y.Dom.setAttribute(el, CLASS_NAME, current.replace(Y.Dom._getClassRegex(className), EMPTY)); + + newClass = Y.Dom._getAttribute(el, CLASS_NAME); + if (current !== newClass) { // else nothing changed + Y.Dom.setAttribute(el, CLASS_NAME, trim(newClass)); // trim after comparing to current class + ret = true; + + if (Y.Dom._getAttribute(el, CLASS_NAME) === '') { // remove class attribute if empty + attr = (el.hasAttribute && el.hasAttribute(_CLASS)) ? _CLASS : CLASS_NAME; + el.removeAttribute(attr); + } + } + + } else { + } + + return ret; + }, + + /** + * Replace a class with another class for a given element or collection of elements. + * If no oldClassName is present, the newClassName is simply added. + * @method replaceClass + * @param {String | HTMLElement | Array} el The element or collection to remove the class from + * @param {String} oldClassName the class name to be replaced + * @param {String} newClassName the class name that will be replacing the old class name + * @return {Boolean | Array} A pass/fail boolean or array of booleans + */ + replaceClass: function(el, oldClassName, newClassName) { + return Y.Dom.batch(el, Y.Dom._replaceClass, { from: oldClassName, to: newClassName }); + }, + + _replaceClass: function(el, classObj) { + var className, + from, + to, + ret = false, + current; + + if (el && classObj) { + from = classObj.from; + to = classObj.to; + + if (!to) { + ret = false; + } else if (!from) { // just add if no "from" + ret = Y.Dom._addClass(el, classObj.to); + } else if (from !== to) { // else nothing to replace + // May need to lead with DBLSPACE? + current = Y.Dom._getAttribute(el, CLASS_NAME) || EMPTY; + className = (SPACE + current.replace(Y.Dom._getClassRegex(from), SPACE + to). + replace(/\s+/g, SPACE)). // normalize white space + split(Y.Dom._getClassRegex(to)); + + // insert to into what would have been the first occurrence slot + className.splice(1, 0, SPACE + to); + Y.Dom.setAttribute(el, CLASS_NAME, trim(className.join(EMPTY))); + ret = true; + } + } else { + } + + return ret; + }, + + /** + * Returns an ID and applies it to the element "el", if provided. + * @method generateId + * @param {String | HTMLElement | Array} el (optional) An optional element array of elements to add an ID to (no ID is added if one is already present). + * @param {String} prefix (optional) an optional prefix to use (defaults to "yui-gen"). + * @return {String | Array} The generated ID, or array of generated IDs (or original ID if already present on an element) + */ + generateId: function(el, prefix) { + prefix = prefix || 'yui-gen'; + + var f = function(el) { + if (el && el.id) { // do not override existing ID + return el.id; + } + + var id = prefix + YAHOO.env._id_counter++; + + if (el) { + if (el[OWNER_DOCUMENT] && el[OWNER_DOCUMENT].getElementById(id)) { // in case one already exists + // use failed id plus prefix to help ensure uniqueness + return Y.Dom.generateId(el, id + prefix); + } + el.id = id; + } + + return id; + }; + + // batch fails when no element, so just generate and return single ID + return Y.Dom.batch(el, f, Y.Dom, true) || f.apply(Y.Dom, arguments); + }, + + /** + * Determines whether an HTMLElement is an ancestor of another HTML element in the DOM hierarchy. + * @method isAncestor + * @param {String | HTMLElement} haystack The possible ancestor + * @param {String | HTMLElement} needle The possible descendent + * @return {Boolean} Whether or not the haystack is an ancestor of needle + */ + isAncestor: function(haystack, needle) { + haystack = Y.Dom.get(haystack); + needle = Y.Dom.get(needle); + + var ret = false; + + if ( (haystack && needle) && (haystack[NODE_TYPE] && needle[NODE_TYPE]) ) { + if (haystack.contains && haystack !== needle) { // contains returns true when equal + ret = haystack.contains(needle); + } + else if (haystack.compareDocumentPosition) { // gecko + ret = !!(haystack.compareDocumentPosition(needle) & 16); + } + } else { + } + return ret; + }, + + /** + * Determines whether an HTMLElement is present in the current document. + * @method inDocument + * @param {String | HTMLElement} el The element to search for + * @param {Object} doc An optional document to search, defaults to element's owner document + * @return {Boolean} Whether or not the element is present in the current document + */ + inDocument: function(el, doc) { + return Y.Dom._inDoc(Y.Dom.get(el), doc); + }, + + _inDoc: function(el, doc) { + var ret = false; + if (el && el[TAG_NAME]) { + doc = doc || el[OWNER_DOCUMENT]; + ret = Y.Dom.isAncestor(doc[DOCUMENT_ELEMENT], el); + } else { + } + return ret; + }, + + /** + * Returns an array of HTMLElements that pass the test applied by supplied boolean method. + * For optimized performance, include a tag and/or root node when possible. + * Note: This method operates against a live collection, so modifying the + * collection in the callback (removing/appending nodes, etc.) will have + * side effects. Instead you should iterate the returned nodes array, + * as you would with the native "getElementsByTagName" method. + * @method getElementsBy + * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. + * @param {String} tag (optional) The tag name of the elements being collected + * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point + * @param {Function} apply (optional) A function to apply to each element when found + * @param {Any} o (optional) An optional arg that is passed to the supplied method + * @param {Boolean} overrides (optional) Whether or not to override the scope of "method" with "o" + * @return {Array} Array of HTMLElements + */ + getElementsBy: function(method, tag, root, apply, o, overrides, firstOnly) { + tag = tag || '*'; + root = (root) ? Y.Dom.get(root) : null || document; + + var ret = (firstOnly) ? null : [], + elements; + + // in case Dom.get() returns null + if (root) { + elements = root.getElementsByTagName(tag); + for (var i = 0, len = elements.length; i < len; ++i) { + if ( method(elements[i]) ) { + if (firstOnly) { + ret = elements[i]; + break; + } else { + ret[ret.length] = elements[i]; + } + } + } + + if (apply) { + Y.Dom.batch(ret, apply, o, overrides); + } + } + + + return ret; + }, + + /** + * Returns the first HTMLElement that passes the test applied by the supplied boolean method. + * @method getElementBy + * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. + * @param {String} tag (optional) The tag name of the elements being collected + * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point + * @return {HTMLElement} + */ + getElementBy: function(method, tag, root) { + return Y.Dom.getElementsBy(method, tag, root, null, null, null, true); + }, + + /** + * Runs the supplied method against each item in the Collection/Array. + * The method is called with the element(s) as the first arg, and the optional param as the second ( method(el, o) ). + * @method batch + * @param {String | HTMLElement | Array} el (optional) An element or array of elements to apply the method to + * @param {Function} method The method to apply to the element(s) + * @param {Any} o (optional) An optional arg that is passed to the supplied method + * @param {Boolean} overrides (optional) Whether or not to override the scope of "method" with "o" + * @return {Any | Array} The return value(s) from the supplied method + */ + batch: function(el, method, o, overrides) { + var collection = [], + scope = (overrides) ? o : null; + + el = (el && (el[TAG_NAME] || el.item)) ? el : Y.Dom.get(el); // skip get() when possible + if (el && method) { + if (el[TAG_NAME] || el.length === undefined) { // element or not array-like + return method.call(scope, el, o); + } + + for (var i = 0; i < el.length; ++i) { + collection[collection.length] = method.call(scope || el[i], el[i], o); + } + } else { + return false; + } + return collection; + }, + + /** + * Returns the height of the document. + * @method getDocumentHeight + * @return {Int} The height of the actual document (which includes the body and its margin). + */ + getDocumentHeight: function() { + var scrollHeight = (document[COMPAT_MODE] != CSS1_COMPAT || isSafari) ? document.body.scrollHeight : documentElement.scrollHeight, + h = Math.max(scrollHeight, Y.Dom.getViewportHeight()); + + return h; + }, + + /** + * Returns the width of the document. + * @method getDocumentWidth + * @return {Int} The width of the actual document (which includes the body and its margin). + */ + getDocumentWidth: function() { + var scrollWidth = (document[COMPAT_MODE] != CSS1_COMPAT || isSafari) ? document.body.scrollWidth : documentElement.scrollWidth, + w = Math.max(scrollWidth, Y.Dom.getViewportWidth()); + return w; + }, + + /** + * Returns the current height of the viewport. + * @method getViewportHeight + * @return {Int} The height of the viewable area of the page (excludes scrollbars). + */ + getViewportHeight: function() { + var height = self.innerHeight, // Safari, Opera + mode = document[COMPAT_MODE]; + + if ( (mode || isIE) && !isOpera ) { // IE, Gecko + height = (mode == CSS1_COMPAT) ? + documentElement.clientHeight : // Standards + document.body.clientHeight; // Quirks + } + + return height; + }, + + /** + * Returns the current width of the viewport. + * @method getViewportWidth + * @return {Int} The width of the viewable area of the page (excludes scrollbars). + */ + + getViewportWidth: function() { + var width = self.innerWidth, // Safari + mode = document[COMPAT_MODE]; + + if (mode || isIE) { // IE, Gecko, Opera + width = (mode == CSS1_COMPAT) ? + documentElement.clientWidth : // Standards + document.body.clientWidth; // Quirks + } + return width; + }, + + /** + * Returns the nearest ancestor that passes the test applied by supplied boolean method. + * For performance reasons, IDs are not accepted and argument validation omitted. + * @method getAncestorBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. + * @return {Object} HTMLElement or null if not found + */ + getAncestorBy: function(node, method) { + while ( (node = node[PARENT_NODE]) ) { // NOTE: assignment + if ( Y.Dom._testElement(node, method) ) { + return node; + } + } + + return null; + }, + + /** + * Returns the nearest ancestor with the given className. + * @method getAncestorByClassName + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @param {String} className + * @return {Object} HTMLElement + */ + getAncestorByClassName: function(node, className) { + node = Y.Dom.get(node); + if (!node) { + return null; + } + var method = function(el) { return Y.Dom.hasClass(el, className); }; + return Y.Dom.getAncestorBy(node, method); + }, + + /** + * Returns the nearest ancestor with the given tagName. + * @method getAncestorByTagName + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @param {String} tagName + * @return {Object} HTMLElement + */ + getAncestorByTagName: function(node, tagName) { + node = Y.Dom.get(node); + if (!node) { + return null; + } + var method = function(el) { + return el[TAG_NAME] && el[TAG_NAME].toUpperCase() == tagName.toUpperCase(); + }; + + return Y.Dom.getAncestorBy(node, method); + }, + + /** + * Returns the previous sibling that is an HTMLElement. + * For performance reasons, IDs are not accepted and argument validation omitted. + * Returns the nearest HTMLElement sibling if no method provided. + * @method getPreviousSiblingBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test siblings + * that receives the sibling node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getPreviousSiblingBy: function(node, method) { + while (node) { + node = node.previousSibling; + if ( Y.Dom._testElement(node, method) ) { + return node; + } + } + return null; + }, + + /** + * Returns the previous sibling that is an HTMLElement + * @method getPreviousSibling + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getPreviousSibling: function(node) { + node = Y.Dom.get(node); + if (!node) { + return null; + } + + return Y.Dom.getPreviousSiblingBy(node); + }, + + /** + * Returns the next HTMLElement sibling that passes the boolean method. + * For performance reasons, IDs are not accepted and argument validation omitted. + * Returns the nearest HTMLElement sibling if no method provided. + * @method getNextSiblingBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test siblings + * that receives the sibling node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getNextSiblingBy: function(node, method) { + while (node) { + node = node.nextSibling; + if ( Y.Dom._testElement(node, method) ) { + return node; + } + } + return null; + }, + + /** + * Returns the next sibling that is an HTMLElement + * @method getNextSibling + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getNextSibling: function(node) { + node = Y.Dom.get(node); + if (!node) { + return null; + } + + return Y.Dom.getNextSiblingBy(node); + }, + + /** + * Returns the first HTMLElement child that passes the test method. + * @method getFirstChildBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test children + * that receives the node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getFirstChildBy: function(node, method) { + var child = ( Y.Dom._testElement(node.firstChild, method) ) ? node.firstChild : null; + return child || Y.Dom.getNextSiblingBy(node.firstChild, method); + }, + + /** + * Returns the first HTMLElement child. + * @method getFirstChild + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getFirstChild: function(node, method) { + node = Y.Dom.get(node); + if (!node) { + return null; + } + return Y.Dom.getFirstChildBy(node); + }, + + /** + * Returns the last HTMLElement child that passes the test method. + * @method getLastChildBy + * @param {HTMLElement} node The HTMLElement to use as the starting point + * @param {Function} method A boolean function used to test children + * that receives the node being tested as its only argument + * @return {Object} HTMLElement or null if not found + */ + getLastChildBy: function(node, method) { + if (!node) { + return null; + } + var child = ( Y.Dom._testElement(node.lastChild, method) ) ? node.lastChild : null; + return child || Y.Dom.getPreviousSiblingBy(node.lastChild, method); + }, + + /** + * Returns the last HTMLElement child. + * @method getLastChild + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Object} HTMLElement or null if not found + */ + getLastChild: function(node) { + node = Y.Dom.get(node); + return Y.Dom.getLastChildBy(node); + }, + + /** + * Returns an array of HTMLElement childNodes that pass the test method. + * @method getChildrenBy + * @param {HTMLElement} node The HTMLElement to start from + * @param {Function} method A boolean function used to test children + * that receives the node being tested as its only argument + * @return {Array} A static array of HTMLElements + */ + getChildrenBy: function(node, method) { + var child = Y.Dom.getFirstChildBy(node, method), + children = child ? [child] : []; + + Y.Dom.getNextSiblingBy(child, function(node) { + if ( !method || method(node) ) { + children[children.length] = node; + } + return false; // fail test to collect all children + }); + + return children; + }, + + /** + * Returns an array of HTMLElement childNodes. + * @method getChildren + * @param {String | HTMLElement} node The HTMLElement or an ID to use as the starting point + * @return {Array} A static array of HTMLElements + */ + getChildren: function(node) { + node = Y.Dom.get(node); + if (!node) { + } + + return Y.Dom.getChildrenBy(node); + }, + + /** + * Returns the left scroll value of the document + * @method getDocumentScrollLeft + * @param {HTMLDocument} document (optional) The document to get the scroll value of + * @return {Int} The amount that the document is scrolled to the left + */ + getDocumentScrollLeft: function(doc) { + doc = doc || document; + return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft); + }, + + /** + * Returns the top scroll value of the document + * @method getDocumentScrollTop + * @param {HTMLDocument} document (optional) The document to get the scroll value of + * @return {Int} The amount that the document is scrolled to the top + */ + getDocumentScrollTop: function(doc) { + doc = doc || document; + return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop); + }, + + /** + * Inserts the new node as the previous sibling of the reference node + * @method insertBefore + * @param {String | HTMLElement} newNode The node to be inserted + * @param {String | HTMLElement} referenceNode The node to insert the new node before + * @return {HTMLElement} The node that was inserted (or null if insert fails) + */ + insertBefore: function(newNode, referenceNode) { + newNode = Y.Dom.get(newNode); + referenceNode = Y.Dom.get(referenceNode); + + if (!newNode || !referenceNode || !referenceNode[PARENT_NODE]) { + return null; + } + + return referenceNode[PARENT_NODE].insertBefore(newNode, referenceNode); + }, + + /** + * Inserts the new node as the next sibling of the reference node + * @method insertAfter + * @param {String | HTMLElement} newNode The node to be inserted + * @param {String | HTMLElement} referenceNode The node to insert the new node after + * @return {HTMLElement} The node that was inserted (or null if insert fails) + */ + insertAfter: function(newNode, referenceNode) { + newNode = Y.Dom.get(newNode); + referenceNode = Y.Dom.get(referenceNode); + + if (!newNode || !referenceNode || !referenceNode[PARENT_NODE]) { + return null; + } + + if (referenceNode.nextSibling) { + return referenceNode[PARENT_NODE].insertBefore(newNode, referenceNode.nextSibling); + } else { + return referenceNode[PARENT_NODE].appendChild(newNode); + } + }, + + /** + * Creates a Region based on the viewport relative to the document. + * @method getClientRegion + * @return {Region} A Region object representing the viewport which accounts for document scroll + */ + getClientRegion: function() { + var t = Y.Dom.getDocumentScrollTop(), + l = Y.Dom.getDocumentScrollLeft(), + r = Y.Dom.getViewportWidth() + l, + b = Y.Dom.getViewportHeight() + t; + + return new Y.Region(t, r, b, l); + }, + + /** + * Provides a normalized attribute interface. + * @method setAttribute + * @param {String | HTMLElement} el The target element for the attribute. + * @param {String} attr The attribute to set. + * @param {String} val The value of the attribute. + */ + setAttribute: function(el, attr, val) { + Y.Dom.batch(el, Y.Dom._setAttribute, { attr: attr, val: val }); + }, + + _setAttribute: function(el, args) { + var attr = Y.Dom._toCamel(args.attr), + val = args.val; + + if (el && el.setAttribute) { + // set as DOM property, except for BUTTON, which errors on property setter + if (Y.Dom.DOT_ATTRIBUTES[attr] && el.tagName && el.tagName != 'BUTTON') { + el[attr] = val; + } else { + attr = Y.Dom.CUSTOM_ATTRIBUTES[attr] || attr; + el.setAttribute(attr, val); + } + } else { + } + }, + + /** + * Provides a normalized attribute interface. + * @method getAttribute + * @param {String | HTMLElement} el The target element for the attribute. + * @param {String} attr The attribute to get. + * @return {String} The current value of the attribute. + */ + getAttribute: function(el, attr) { + return Y.Dom.batch(el, Y.Dom._getAttribute, attr); + }, + + + _getAttribute: function(el, attr) { + var val; + attr = Y.Dom.CUSTOM_ATTRIBUTES[attr] || attr; + + if (Y.Dom.DOT_ATTRIBUTES[attr]) { + val = el[attr]; + } else if (el && 'getAttribute' in el) { + if (/^(?:href|src)$/.test(attr)) { // use IE flag to return exact value + val = el.getAttribute(attr, 2); + } else { + val = el.getAttribute(attr); + } + } else { + } + + return val; + }, + + _toCamel: function(property) { + var c = propertyCache; + + function tU(x,l) { + return l.toUpperCase(); + } + + return c[property] || (c[property] = property.indexOf('-') === -1 ? + property : + property.replace( /-([a-z])/gi, tU )); + }, + + _getClassRegex: function(className) { + var re; + if (className !== undefined) { // allow empty string to pass + if (className.exec) { // already a RegExp + re = className; + } else { + re = reCache[className]; + if (!re) { + // escape special chars (".", "[", etc.) + className = className.replace(Y.Dom._patterns.CLASS_RE_TOKENS, '\\$1'); + className = className.replace(/\s+/g, SPACE); // convert line breaks and other delims + re = reCache[className] = new RegExp(C_START + className + C_END, G); + } + } + } + return re; + }, + + _patterns: { + ROOT_TAG: /^body|html$/i, // body for quirks mode, html for standards, + CLASS_RE_TOKENS: /([\.\(\)\^\$\*\+\?\|\[\]\{\}\\])/g + }, + + + _testElement: function(node, method) { + return node && node[NODE_TYPE] == 1 && ( !method || method(node) ); + }, + + _calcBorders: function(node, xy2) { + var t = parseInt(Y.Dom[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0, + l = parseInt(Y.Dom[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0; + if (isGecko) { + if (RE_TABLE.test(node[TAG_NAME])) { + t = 0; + l = 0; + } + } + xy2[0] += l; + xy2[1] += t; + return xy2; + } + }; + + var _getComputedStyle = Y.Dom[GET_COMPUTED_STYLE]; + // fix opera computedStyle default color unit (convert to rgb) + if (UA.opera) { + Y.Dom[GET_COMPUTED_STYLE] = function(node, att) { + var val = _getComputedStyle(node, att); + if (RE_COLOR.test(att)) { + val = Y.Dom.Color.toRGB(val); + } + + return val; + }; + + } + + // safari converts transparent to rgba(), others use "transparent" + if (UA.webkit) { + Y.Dom[GET_COMPUTED_STYLE] = function(node, att) { + var val = _getComputedStyle(node, att); + + if (val === 'rgba(0, 0, 0, 0)') { + val = 'transparent'; + } + + return val; + }; + + } + + if (UA.ie && UA.ie >= 8) { + Y.Dom.DOT_ATTRIBUTES.type = true; // IE 8 errors on input.setAttribute('type') + } +})(); +/** + * A region is a representation of an object on a grid. It is defined + * by the top, right, bottom, left extents, so is rectangular by default. If + * other shapes are required, this class could be extended to support it. + * @namespace YAHOO.util + * @class Region + * @param {Int} t the top extent + * @param {Int} r the right extent + * @param {Int} b the bottom extent + * @param {Int} l the left extent + * @constructor + */ +YAHOO.util.Region = function(t, r, b, l) { + + /** + * The region's top extent + * @property top + * @type Int + */ + this.top = t; + + /** + * The region's top extent + * @property y + * @type Int + */ + this.y = t; + + /** + * The region's top extent as index, for symmetry with set/getXY + * @property 1 + * @type Int + */ + this[1] = t; + + /** + * The region's right extent + * @property right + * @type int + */ + this.right = r; + + /** + * The region's bottom extent + * @property bottom + * @type Int + */ + this.bottom = b; + + /** + * The region's left extent + * @property left + * @type Int + */ + this.left = l; + + /** + * The region's left extent + * @property x + * @type Int + */ + this.x = l; + + /** + * The region's left extent as index, for symmetry with set/getXY + * @property 0 + * @type Int + */ + this[0] = l; + + /** + * The region's total width + * @property width + * @type Int + */ + this.width = this.right - this.left; + + /** + * The region's total height + * @property height + * @type Int + */ + this.height = this.bottom - this.top; +}; + +/** + * Returns true if this region contains the region passed in + * @method contains + * @param {Region} region The region to evaluate + * @return {Boolean} True if the region is contained with this region, + * else false + */ +YAHOO.util.Region.prototype.contains = function(region) { + return ( region.left >= this.left && + region.right <= this.right && + region.top >= this.top && + region.bottom <= this.bottom ); + +}; + +/** + * Returns the area of the region + * @method getArea + * @return {Int} the region's area + */ +YAHOO.util.Region.prototype.getArea = function() { + return ( (this.bottom - this.top) * (this.right - this.left) ); +}; + +/** + * Returns the region where the passed in region overlaps with this one + * @method intersect + * @param {Region} region The region that intersects + * @return {Region} The overlap region, or null if there is no overlap + */ +YAHOO.util.Region.prototype.intersect = function(region) { + var t = Math.max( this.top, region.top ), + r = Math.min( this.right, region.right ), + b = Math.min( this.bottom, region.bottom ), + l = Math.max( this.left, region.left ); + + if (b >= t && r >= l) { + return new YAHOO.util.Region(t, r, b, l); + } else { + return null; + } +}; + +/** + * Returns the region representing the smallest region that can contain both + * the passed in region and this region. + * @method union + * @param {Region} region The region that to create the union with + * @return {Region} The union region + */ +YAHOO.util.Region.prototype.union = function(region) { + var t = Math.min( this.top, region.top ), + r = Math.max( this.right, region.right ), + b = Math.max( this.bottom, region.bottom ), + l = Math.min( this.left, region.left ); + + return new YAHOO.util.Region(t, r, b, l); +}; + +/** + * toString + * @method toString + * @return string the region properties + */ +YAHOO.util.Region.prototype.toString = function() { + return ( "Region {" + + "top: " + this.top + + ", right: " + this.right + + ", bottom: " + this.bottom + + ", left: " + this.left + + ", height: " + this.height + + ", width: " + this.width + + "}" ); +}; + +/** + * Returns a region that is occupied by the DOM element + * @method getRegion + * @param {HTMLElement} el The element + * @return {Region} The region that the element occupies + * @static + */ +YAHOO.util.Region.getRegion = function(el) { + var p = YAHOO.util.Dom.getXY(el), + t = p[1], + r = p[0] + el.offsetWidth, + b = p[1] + el.offsetHeight, + l = p[0]; + + return new YAHOO.util.Region(t, r, b, l); +}; + +///////////////////////////////////////////////////////////////////////////// + + +/** + * A point is a region that is special in that it represents a single point on + * the grid. + * @namespace YAHOO.util + * @class Point + * @param {Int} x The X position of the point + * @param {Int} y The Y position of the point + * @constructor + * @extends YAHOO.util.Region + */ +YAHOO.util.Point = function(x, y) { + if (YAHOO.lang.isArray(x)) { // accept input from Dom.getXY, Event.getXY, etc. + y = x[1]; // dont blow away x yet + x = x[0]; + } + + YAHOO.util.Point.superclass.constructor.call(this, y, x, y, x); +}; + +YAHOO.extend(YAHOO.util.Point, YAHOO.util.Region); + +(function() { +/** + * Internal methods used to add style management functionality to DOM. + * @module dom + * @class IEStyle + * @namespace YAHOO.util.Dom + */ + +var Y = YAHOO.util, + CLIENT_TOP = 'clientTop', + CLIENT_LEFT = 'clientLeft', + PARENT_NODE = 'parentNode', + RIGHT = 'right', + HAS_LAYOUT = 'hasLayout', + PX = 'px', + OPACITY = 'opacity', + AUTO = 'auto', + BORDER_LEFT_WIDTH = 'borderLeftWidth', + BORDER_TOP_WIDTH = 'borderTopWidth', + BORDER_RIGHT_WIDTH = 'borderRightWidth', + BORDER_BOTTOM_WIDTH = 'borderBottomWidth', + VISIBLE = 'visible', + TRANSPARENT = 'transparent', + HEIGHT = 'height', + WIDTH = 'width', + STYLE = 'style', + CURRENT_STYLE = 'currentStyle', + +// IE getComputedStyle +// TODO: unit-less lineHeight (e.g. 1.22) + re_size = /^width|height$/, + re_unit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i, + + ComputedStyle = { + /** + * @method get + * @description Method used by DOM to get style information for IE + * @param {HTMLElement} el The element to check + * @param {String} property The property to check + * @returns {String} The computed style + */ + get: function(el, property) { + var value = '', + current = el[CURRENT_STYLE][property]; + + if (property === OPACITY) { + value = Y.Dom.getStyle(el, OPACITY); + } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert + value = current; + } else if (Y.Dom.IE_COMPUTED[property]) { // use compute function + value = Y.Dom.IE_COMPUTED[property](el, property); + } else if (re_unit.test(current)) { // convert to pixel + value = Y.Dom.IE.ComputedStyle.getPixel(el, property); + } else { + value = current; + } + + return value; + }, + /** + * @method getOffset + * @description Determine the offset of an element + * @param {HTMLElement} el The element to check + * @param {String} prop The property to check. + * @return {String} The offset + */ + getOffset: function(el, prop) { + var current = el[CURRENT_STYLE][prop], // value of "width", "top", etc. + capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc. + offset = 'offset' + capped, // "offsetWidth", "offsetTop", etc. + pixel = 'pixel' + capped, // "pixelWidth", "pixelTop", etc. + value = '', + actual; + + if (current == AUTO) { + actual = el[offset]; // offsetHeight/Top etc. + if (actual === undefined) { // likely "right" or "bottom" + value = 0; + } + + value = actual; + if (re_size.test(prop)) { // account for box model diff + el[STYLE][prop] = actual; + if (el[offset] > actual) { + // the difference is padding + border (works in Standards & Quirks modes) + value = actual - (el[offset] - actual); + } + el[STYLE][prop] = AUTO; // revert to auto + } + } else { // convert units to px + if (!el[STYLE][pixel] && !el[STYLE][prop]) { // need to map style.width to currentStyle (no currentStyle.pixelWidth) + el[STYLE][prop] = current; // no style.pixelWidth if no style.width + } + value = el[STYLE][pixel]; + } + return value + PX; + }, + /** + * @method getBorderWidth + * @description Try to determine the width of an elements border + * @param {HTMLElement} el The element to check + * @param {String} property The property to check + * @return {String} The elements border width + */ + getBorderWidth: function(el, property) { + // clientHeight/Width = paddingBox (e.g. offsetWidth - borderWidth) + // clientTop/Left = borderWidth + var value = null; + if (!el[CURRENT_STYLE][HAS_LAYOUT]) { // TODO: unset layout? + el[STYLE].zoom = 1; // need layout to measure client + } + + switch(property) { + case BORDER_TOP_WIDTH: + value = el[CLIENT_TOP]; + break; + case BORDER_BOTTOM_WIDTH: + value = el.offsetHeight - el.clientHeight - el[CLIENT_TOP]; + break; + case BORDER_LEFT_WIDTH: + value = el[CLIENT_LEFT]; + break; + case BORDER_RIGHT_WIDTH: + value = el.offsetWidth - el.clientWidth - el[CLIENT_LEFT]; + break; + } + return value + PX; + }, + /** + * @method getPixel + * @description Get the pixel value from a style property + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The pixel value + */ + getPixel: function(node, att) { + // use pixelRight to convert to px + var val = null, + styleRight = node[CURRENT_STYLE][RIGHT], + current = node[CURRENT_STYLE][att]; + + node[STYLE][RIGHT] = current; + val = node[STYLE].pixelRight; + node[STYLE][RIGHT] = styleRight; // revert + + return val + PX; + }, + + /** + * @method getMargin + * @description Get the margin value from a style property + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The margin value + */ + getMargin: function(node, att) { + var val; + if (node[CURRENT_STYLE][att] == AUTO) { + val = 0 + PX; + } else { + val = Y.Dom.IE.ComputedStyle.getPixel(node, att); + } + return val; + }, + + /** + * @method getVisibility + * @description Get the visibility of an element + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The value + */ + getVisibility: function(node, att) { + var current; + while ( (current = node[CURRENT_STYLE]) && current[att] == 'inherit') { // NOTE: assignment in test + node = node[PARENT_NODE]; + } + return (current) ? current[att] : VISIBLE; + }, + + /** + * @method getColor + * @description Get the color of an element + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The value + */ + getColor: function(node, att) { + return Y.Dom.Color.toRGB(node[CURRENT_STYLE][att]) || TRANSPARENT; + }, + + /** + * @method getBorderColor + * @description Get the bordercolor of an element + * @param {HTMLElement} node The element to check + * @param {String} att The attribute to check + * @return {String} The value + */ + getBorderColor: function(node, att) { + var current = node[CURRENT_STYLE], + val = current[att] || current.color; + return Y.Dom.Color.toRGB(Y.Dom.Color.toHex(val)); + } + + }, + +//fontSize: getPixelFont, + IEComputed = {}; + +IEComputed.top = IEComputed.right = IEComputed.bottom = IEComputed.left = + IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset; + +IEComputed.color = ComputedStyle.getColor; + +IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] = + IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] = + ComputedStyle.getBorderWidth; + +IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom = + IEComputed.marginLeft = ComputedStyle.getMargin; + +IEComputed.visibility = ComputedStyle.getVisibility; +IEComputed.borderColor = IEComputed.borderTopColor = + IEComputed.borderRightColor = IEComputed.borderBottomColor = + IEComputed.borderLeftColor = ComputedStyle.getBorderColor; + +Y.Dom.IE_COMPUTED = IEComputed; +Y.Dom.IE_ComputedStyle = ComputedStyle; +})(); +(function() { +/** + * Add style management functionality to DOM. + * @module dom + * @class Color + * @namespace YAHOO.util.Dom + */ + +var TO_STRING = 'toString', + PARSE_INT = parseInt, + RE = RegExp, + Y = YAHOO.util; + +Y.Dom.Color = { + /** + * @property KEYWORDS + * @type Object + * @description Color keywords used when converting to Hex + */ + KEYWORDS: { + black: '000', + silver: 'c0c0c0', + gray: '808080', + white: 'fff', + maroon: '800000', + red: 'f00', + purple: '800080', + fuchsia: 'f0f', + green: '008000', + lime: '0f0', + olive: '808000', + yellow: 'ff0', + navy: '000080', + blue: '00f', + teal: '008080', + aqua: '0ff' + }, + /** + * @property re_RGB + * @private + * @type Regex + * @description Regex to parse rgb(0,0,0) formatted strings + */ + re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i, + /** + * @property re_hex + * @private + * @type Regex + * @description Regex to parse #123456 formatted strings + */ + re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i, + /** + * @property re_hex3 + * @private + * @type Regex + * @description Regex to parse #123 formatted strings + */ + re_hex3: /([0-9A-F])/gi, + /** + * @method toRGB + * @description Converts a hex or color string to an rgb string: rgb(0,0,0) + * @param {String} val The string to convert to RGB notation. + * @returns {String} The converted string + */ + toRGB: function(val) { + if (!Y.Dom.Color.re_RGB.test(val)) { + val = Y.Dom.Color.toHex(val); + } + + if(Y.Dom.Color.re_hex.exec(val)) { + val = 'rgb(' + [ + PARSE_INT(RE.$1, 16), + PARSE_INT(RE.$2, 16), + PARSE_INT(RE.$3, 16) + ].join(', ') + ')'; + } + return val; + }, + /** + * @method toHex + * @description Converts an rgb or color string to a hex string: #123456 + * @param {String} val The string to convert to hex notation. + * @returns {String} The converted string + */ + toHex: function(val) { + val = Y.Dom.Color.KEYWORDS[val] || val; + if (Y.Dom.Color.re_RGB.exec(val)) { + val = [ + Number(RE.$1).toString(16), + Number(RE.$2).toString(16), + Number(RE.$3).toString(16) + ]; + + for (var i = 0; i < val.length; i++) { + if (val[i].length < 2) { + val[i] = '0' + val[i]; + } + } + + val = val.join(''); + } + + if (val.length < 6) { + val = val.replace(Y.Dom.Color.re_hex3, '$1$1'); + } + + if (val !== 'transparent' && val.indexOf('#') < 0) { + val = '#' + val; + } + + return val.toUpperCase(); + } +}; +}()); +YAHOO.register("dom", YAHOO.util.Dom, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-debug.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-debug.js new file mode 100644 index 0000000..2a955b6 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-debug.js @@ -0,0 +1,283 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +/** + * Augments the Event Utility with a delegate method that + * facilitates easy creation of delegated event listeners. (Note: Using CSS + * selectors as the filtering criteria for delegated event listeners requires + * inclusion of the Selector Utility.) + * + * @module event-delegate + * @title Event Utility Event Delegation Module + * @namespace YAHOO.util + * @requires event + */ + +(function () { + + var Event = YAHOO.util.Event, + Lang = YAHOO.lang, + delegates = [], + + + getMatch = function(el, selector, container) { + + var returnVal; + + if (!el || el === container) { + returnVal = false; + } + else { + returnVal = YAHOO.util.Selector.test(el, selector) ? el: getMatch(el.parentNode, selector, container); + } + + return returnVal; + + }; + + + Lang.augmentObject(Event, { + + /** + * Creates a delegate function used to call event listeners specified + * via the YAHOO.util.Event.delegate method. + * + * @method _createDelegate + * + * @param {Function} fn The method (event listener) to call. + * @param {Function|string} filter Function or CSS selector used to + * determine for what element(s) the event listener should be called. + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the listener. + * @param {Boolean|object} overrideContext If true, the value of the + * obj parameter becomes the execution context + * of the listener. If an object, this object + * becomes the execution context. + * @return {Function} Function that will call the event listener + * specified by the YAHOO.util.Event.delegate method. + * @private + * @for Event + * @static + */ + _createDelegate: function (fn, filter, obj, overrideContext) { + + return function (event) { + + var container = this, + target = Event.getTarget(event), + selector = filter, + + // The user might have specified the document object + // as the delegation container, in which case it is not + // nessary to scope the provided CSS selector(s) to the + // delegation container + bDocument = (container.nodeType === 9), + + matchedEl, + context, + sID, + sIDSelector; + + + if (Lang.isFunction(filter)) { + matchedEl = filter(target); + } + else if (Lang.isString(filter)) { + + if (!bDocument) { + + sID = container.id; + + if (!sID) { + sID = Event.generateId(container); + } + + // Scope all selectors to the container + sIDSelector = ("#" + sID + " "); + selector = (sIDSelector + filter).replace(/,/gi, ("," + sIDSelector)); + + } + + + if (YAHOO.util.Selector.test(target, selector)) { + matchedEl = target; + } + else if (YAHOO.util.Selector.test(target, ((selector.replace(/,/gi, " *,")) + " *"))) { + + // The target is a descendant of an element matching + // the selector, so crawl up to find the ancestor that + // matches the selector + + matchedEl = getMatch(target, selector, container); + + } + + } + + + if (matchedEl) { + + // The default context for delegated listeners is the + // element that matched the filter. + + context = matchedEl; + + if (overrideContext) { + if (overrideContext === true) { + context = obj; + } else { + context = overrideContext; + } + } + + // Call the listener passing in the container and the + // element that matched the filter in case the user + // needs those. + + return fn.call(context, event, matchedEl, container, obj); + + } + + }; + + }, + + + /** + * Appends a delegated event listener. Delegated event listeners + * receive three arguments by default: the DOM event, the element + * specified by the filtering function or CSS selector, and the + * container element (the element to which the event listener is + * bound). (Note: Using the delegate method requires the event-delegate + * module. Using CSS selectors as the filtering criteria for delegated + * event listeners requires inclusion of the Selector Utility.) + * + * @method delegate + * + * @param {String|HTMLElement|Array|NodeList} container An id, an element + * reference, or a collection of ids and/or elements to assign the + * listener to. + * @param {String} type The type of event listener to append + * @param {Function} fn The method the event invokes + * @param {Function|string} filter Function or CSS selector used to + * determine for what element(s) the event listener should be called. + * When a function is specified, the function should return an + * HTML element. Using a CSS Selector requires the inclusion of the + * CSS Selector Utility. + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the listener + * @param {Boolean|object} overrideContext If true, the value of the obj parameter becomes + * the execution context of the listener. If an + * object, this object becomes the execution + * context. + * @return {Boolean} Returns true if the action was successful or defered, + * false if one or more of the elements + * could not have the listener attached, + * or if the operation throws an exception. + * @static + * @for Event + */ + delegate: function (container, type, fn, filter, obj, overrideContext) { + + var sType = type, + fnMouseDelegate, + fnDelegate; + + + if (Lang.isString(filter) && !YAHOO.util.Selector) { + YAHOO.log("Using a CSS selector to define the filtering criteria for a delegated listener requires the Selector Utility.", "error", "Event"); + return false; + } + + + if (type == "mouseenter" || type == "mouseleave") { + + if (!Event._createMouseDelegate) { + YAHOO.log("Delegating a " + type + " event requires the event-mouseenter module.", "error", "Event"); + return false; + } + + // Look up the real event--either mouseover or mouseout + sType = Event._getType(type); + + fnMouseDelegate = Event._createMouseDelegate(fn, obj, overrideContext); + + fnDelegate = Event._createDelegate(function (event, matchedEl, container) { + + return fnMouseDelegate.call(matchedEl, event, container); + + }, filter, obj, overrideContext); + + } + else { + + fnDelegate = Event._createDelegate(fn, filter, obj, overrideContext); + + } + + delegates.push([container, sType, fn, fnDelegate]); + + return Event.on(container, sType, fnDelegate); + + }, + + + /** + * Removes a delegated event listener. + * + * @method removeDelegate + * + * @param {String|HTMLElement|Array|NodeList} container An id, an element + * reference, or a collection of ids and/or elements to remove + * the listener from. + * @param {String} type The type of event to remove. + * @param {Function} fn The method the event invokes. If fn is + * undefined, then all event listeners for the type of event are + * removed. + * @return {boolean} Returns true if the unbind was successful, false + * otherwise. + * @static + * @for Event + */ + removeDelegate: function (container, type, fn) { + + var sType = type, + returnVal = false, + index, + cacheItem; + + // Look up the real event--either mouseover or mouseout + if (type == "mouseenter" || type == "mouseleave") { + sType = Event._getType(type); + } + + index = Event._getCacheIndex(delegates, container, sType, fn); + + if (index >= 0) { + cacheItem = delegates[index]; + } + + + if (container && cacheItem) { + + returnVal = Event.removeListener(cacheItem[0], cacheItem[1], cacheItem[3]); + + if (returnVal) { + delete delegates[index][2]; + delete delegates[index][3]; + delegates.splice(index, 1); + } + + } + + return returnVal; + + } + + }); + +}()); +YAHOO.register("event-delegate", YAHOO.util.Event, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-min.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-min.js new file mode 100644 index 0000000..5163f7a --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate-min.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +(function(){var A=YAHOO.util.Event,C=YAHOO.lang,B=[],D=function(H,E,F){var G;if(!H||H===F){G=false;}else{G=YAHOO.util.Selector.test(H,E)?H:D(H.parentNode,E,F);}return G;};C.augmentObject(A,{_createDelegate:function(F,E,G,H){return function(I){var J=this,N=A.getTarget(I),L=E,P=(J.nodeType===9),Q,K,O,M;if(C.isFunction(E)){Q=E(N);}else{if(C.isString(E)){if(!P){O=J.id;if(!O){O=A.generateId(J);}M=("#"+O+" ");L=(M+E).replace(/,/gi,(","+M));}if(YAHOO.util.Selector.test(N,L)){Q=N;}else{if(YAHOO.util.Selector.test(N,((L.replace(/,/gi," *,"))+" *"))){Q=D(N,L,J);}}}}if(Q){K=Q;if(H){if(H===true){K=G;}else{K=H;}}return F.call(K,I,Q,J,G);}};},delegate:function(F,J,L,G,H,I){var E=J,K,M;if(C.isString(G)&&!YAHOO.util.Selector){return false;}if(J=="mouseenter"||J=="mouseleave"){if(!A._createMouseDelegate){return false;}E=A._getType(J);K=A._createMouseDelegate(L,H,I);M=A._createDelegate(function(P,O,N){return K.call(O,P,N);},G,H,I);}else{M=A._createDelegate(L,G,H,I);}B.push([F,E,L,M]);return A.on(F,E,M);},removeDelegate:function(F,J,I){var K=J,H=false,G,E;if(J=="mouseenter"||J=="mouseleave"){K=A._getType(J);}G=A._getCacheIndex(B,F,K,I);if(G>=0){E=B[G];}if(F&&E){H=A.removeListener(E[0],E[1],E[3]);if(H){delete B[G][2];delete B[G][3];B.splice(G,1);}}return H;}});}());YAHOO.register("event-delegate",YAHOO.util.Event,{version:"2.9.0",build:"2800"}); \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate.js new file mode 100644 index 0000000..974bf34 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-delegate/event-delegate.js @@ -0,0 +1,281 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +/** + * Augments the Event Utility with a delegate method that + * facilitates easy creation of delegated event listeners. (Note: Using CSS + * selectors as the filtering criteria for delegated event listeners requires + * inclusion of the Selector Utility.) + * + * @module event-delegate + * @title Event Utility Event Delegation Module + * @namespace YAHOO.util + * @requires event + */ + +(function () { + + var Event = YAHOO.util.Event, + Lang = YAHOO.lang, + delegates = [], + + + getMatch = function(el, selector, container) { + + var returnVal; + + if (!el || el === container) { + returnVal = false; + } + else { + returnVal = YAHOO.util.Selector.test(el, selector) ? el: getMatch(el.parentNode, selector, container); + } + + return returnVal; + + }; + + + Lang.augmentObject(Event, { + + /** + * Creates a delegate function used to call event listeners specified + * via the YAHOO.util.Event.delegate method. + * + * @method _createDelegate + * + * @param {Function} fn The method (event listener) to call. + * @param {Function|string} filter Function or CSS selector used to + * determine for what element(s) the event listener should be called. + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the listener. + * @param {Boolean|object} overrideContext If true, the value of the + * obj parameter becomes the execution context + * of the listener. If an object, this object + * becomes the execution context. + * @return {Function} Function that will call the event listener + * specified by the YAHOO.util.Event.delegate method. + * @private + * @for Event + * @static + */ + _createDelegate: function (fn, filter, obj, overrideContext) { + + return function (event) { + + var container = this, + target = Event.getTarget(event), + selector = filter, + + // The user might have specified the document object + // as the delegation container, in which case it is not + // nessary to scope the provided CSS selector(s) to the + // delegation container + bDocument = (container.nodeType === 9), + + matchedEl, + context, + sID, + sIDSelector; + + + if (Lang.isFunction(filter)) { + matchedEl = filter(target); + } + else if (Lang.isString(filter)) { + + if (!bDocument) { + + sID = container.id; + + if (!sID) { + sID = Event.generateId(container); + } + + // Scope all selectors to the container + sIDSelector = ("#" + sID + " "); + selector = (sIDSelector + filter).replace(/,/gi, ("," + sIDSelector)); + + } + + + if (YAHOO.util.Selector.test(target, selector)) { + matchedEl = target; + } + else if (YAHOO.util.Selector.test(target, ((selector.replace(/,/gi, " *,")) + " *"))) { + + // The target is a descendant of an element matching + // the selector, so crawl up to find the ancestor that + // matches the selector + + matchedEl = getMatch(target, selector, container); + + } + + } + + + if (matchedEl) { + + // The default context for delegated listeners is the + // element that matched the filter. + + context = matchedEl; + + if (overrideContext) { + if (overrideContext === true) { + context = obj; + } else { + context = overrideContext; + } + } + + // Call the listener passing in the container and the + // element that matched the filter in case the user + // needs those. + + return fn.call(context, event, matchedEl, container, obj); + + } + + }; + + }, + + + /** + * Appends a delegated event listener. Delegated event listeners + * receive three arguments by default: the DOM event, the element + * specified by the filtering function or CSS selector, and the + * container element (the element to which the event listener is + * bound). (Note: Using the delegate method requires the event-delegate + * module. Using CSS selectors as the filtering criteria for delegated + * event listeners requires inclusion of the Selector Utility.) + * + * @method delegate + * + * @param {String|HTMLElement|Array|NodeList} container An id, an element + * reference, or a collection of ids and/or elements to assign the + * listener to. + * @param {String} type The type of event listener to append + * @param {Function} fn The method the event invokes + * @param {Function|string} filter Function or CSS selector used to + * determine for what element(s) the event listener should be called. + * When a function is specified, the function should return an + * HTML element. Using a CSS Selector requires the inclusion of the + * CSS Selector Utility. + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the listener + * @param {Boolean|object} overrideContext If true, the value of the obj parameter becomes + * the execution context of the listener. If an + * object, this object becomes the execution + * context. + * @return {Boolean} Returns true if the action was successful or defered, + * false if one or more of the elements + * could not have the listener attached, + * or if the operation throws an exception. + * @static + * @for Event + */ + delegate: function (container, type, fn, filter, obj, overrideContext) { + + var sType = type, + fnMouseDelegate, + fnDelegate; + + + if (Lang.isString(filter) && !YAHOO.util.Selector) { + return false; + } + + + if (type == "mouseenter" || type == "mouseleave") { + + if (!Event._createMouseDelegate) { + return false; + } + + // Look up the real event--either mouseover or mouseout + sType = Event._getType(type); + + fnMouseDelegate = Event._createMouseDelegate(fn, obj, overrideContext); + + fnDelegate = Event._createDelegate(function (event, matchedEl, container) { + + return fnMouseDelegate.call(matchedEl, event, container); + + }, filter, obj, overrideContext); + + } + else { + + fnDelegate = Event._createDelegate(fn, filter, obj, overrideContext); + + } + + delegates.push([container, sType, fn, fnDelegate]); + + return Event.on(container, sType, fnDelegate); + + }, + + + /** + * Removes a delegated event listener. + * + * @method removeDelegate + * + * @param {String|HTMLElement|Array|NodeList} container An id, an element + * reference, or a collection of ids and/or elements to remove + * the listener from. + * @param {String} type The type of event to remove. + * @param {Function} fn The method the event invokes. If fn is + * undefined, then all event listeners for the type of event are + * removed. + * @return {boolean} Returns true if the unbind was successful, false + * otherwise. + * @static + * @for Event + */ + removeDelegate: function (container, type, fn) { + + var sType = type, + returnVal = false, + index, + cacheItem; + + // Look up the real event--either mouseover or mouseout + if (type == "mouseenter" || type == "mouseleave") { + sType = Event._getType(type); + } + + index = Event._getCacheIndex(delegates, container, sType, fn); + + if (index >= 0) { + cacheItem = delegates[index]; + } + + + if (container && cacheItem) { + + returnVal = Event.removeListener(cacheItem[0], cacheItem[1], cacheItem[3]); + + if (returnVal) { + delete delegates[index][2]; + delete delegates[index][3]; + delegates.splice(index, 1); + } + + } + + return returnVal; + + } + + }); + +}()); +YAHOO.register("event-delegate", YAHOO.util.Event, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-debug.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-debug.js new file mode 100644 index 0000000..c265487 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-debug.js @@ -0,0 +1,218 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +/** + * Augments the Event Utility with support for the mouseenter and mouseleave + * events: A mouseenter event fires the first time the mouse enters an + * element; a mouseleave event first the first time the mouse leaves an + * element. + * + * @module event-mouseenter + * @title Event Utility mouseenter and mouseout Module + * @namespace YAHOO.util + * @requires event + */ + +(function () { + + var Event = YAHOO.util.Event, + Lang = YAHOO.lang, + + addListener = Event.addListener, + removeListener = Event.removeListener, + getListeners = Event.getListeners, + + delegates = [], + + specialTypes = { + mouseenter: "mouseover", + mouseleave: "mouseout" + }, + + remove = function(el, type, fn) { + + var index = Event._getCacheIndex(delegates, el, type, fn), + cacheItem, + returnVal; + + if (index >= 0) { + cacheItem = delegates[index]; + } + + if (el && cacheItem) { + + // removeListener will translate the value of type + returnVal = removeListener.call(Event, cacheItem[0], type, cacheItem[3]); + + if (returnVal) { + delete delegates[index][2]; + delete delegates[index][3]; + delegates.splice(index, 1); + } + + } + + return returnVal; + + }; + + + Lang.augmentObject(Event._specialTypes, specialTypes); + + Lang.augmentObject(Event, { + + /** + * Creates a delegate function used to call mouseover and mouseleave + * event listeners specified via the + * YAHOO.util.Event.addListener + * or YAHOO.util.Event.on method. + * + * @method _createMouseDelegate + * + * @param {Function} fn The method (event listener) to call + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the listener + * @param {Boolean|object} overrideContext If true, the value of the + * obj parameter becomes the execution context + * of the listener. If an object, this object + * becomes the execution context. + * @return {Function} Function that will call the event listener + * specified by either the YAHOO.util.Event.addListener + * or YAHOO.util.Event.on method. + * @private + * @static + * @for Event + */ + _createMouseDelegate: function (fn, obj, overrideContext) { + + return function (event, container) { + + var el = this, + relatedTarget = Event.getRelatedTarget(event), + context, + args; + + if (el != relatedTarget && !YAHOO.util.Dom.isAncestor(el, relatedTarget)) { + + context = el; + + if (overrideContext) { + if (overrideContext === true) { + context = obj; + } else { + context = overrideContext; + } + } + + // The default args passed back to a mouseenter or + // mouseleave listener are: the event, and any object + // the user passed when subscribing + + args = [event, obj]; + + // Add the element and delegation container as arguments + // when delegating mouseenter and mouseleave + + if (container) { + args.splice(1, 0, el, container); + } + + return fn.apply(context, args); + + } + + }; + + }, + + addListener: function (el, type, fn, obj, overrideContext) { + + var fnDelegate, + returnVal; + + if (specialTypes[type]) { + + fnDelegate = Event._createMouseDelegate(fn, obj, overrideContext); + + fnDelegate.mouseDelegate = true; + + delegates.push([el, type, fn, fnDelegate]); + + // addListener will translate the value of type + returnVal = addListener.call(Event, el, type, fnDelegate); + + } + else { + returnVal = addListener.apply(Event, arguments); + } + + return returnVal; + + }, + + removeListener: function (el, type, fn) { + + var returnVal; + + if (specialTypes[type]) { + returnVal = remove.apply(Event, arguments); + } + else { + returnVal = removeListener.apply(Event, arguments); + } + + return returnVal; + + }, + + getListeners: function (el, type) { + + // If the user specified the type as mouseover or mouseout, + // need to filter out those used by mouseenter and mouseleave. + // If the user specified the type as mouseenter or mouseleave, + // need to filter out the true mouseover and mouseout listeners. + + var listeners = [], + elListeners, + bMouseOverOrOut = (type === "mouseover" || type === "mouseout"), + bMouseDelegate, + i, + l; + + if (type && (bMouseOverOrOut || specialTypes[type])) { + + elListeners = getListeners.call(Event, el, this._getType(type)); + + if (elListeners) { + + for (i=elListeners.length-1; i>-1; i--) { + + l = elListeners[i]; + bMouseDelegate = l.fn.mouseDelegate; + + if ((specialTypes[type] && bMouseDelegate) || (bMouseOverOrOut && !bMouseDelegate)) { + listeners.push(l); + } + + } + + } + + } + else { + listeners = getListeners.apply(Event, arguments); + } + + return (listeners && listeners.length) ? listeners : null; + + } + + }, true); + + Event.on = Event.addListener; + +}()); +YAHOO.register("event-mouseenter", YAHOO.util.Event, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-min.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-min.js new file mode 100644 index 0000000..4a4e951 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter-min.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +(function(){var b=YAHOO.util.Event,g=YAHOO.lang,e=b.addListener,f=b.removeListener,c=b.getListeners,d=[],h={mouseenter:"mouseover",mouseleave:"mouseout"},a=function(n,m,l){var j=b._getCacheIndex(d,n,m,l),i,k;if(j>=0){i=d[j];}if(n&&i){k=f.call(b,i[0],m,i[3]);if(k){delete d[j][2];delete d[j][3];d.splice(j,1);}}return k;};g.augmentObject(b._specialTypes,h);g.augmentObject(b,{_createMouseDelegate:function(i,j,k){return function(q,m){var p=this,l=b.getRelatedTarget(q),o,n;if(p!=l&&!YAHOO.util.Dom.isAncestor(p,l)){o=p;if(k){if(k===true){o=j;}else{o=k;}}n=[q,j];if(m){n.splice(1,0,p,m);}return i.apply(o,n);}};},addListener:function(m,l,k,n,o){var i,j;if(h[l]){i=b._createMouseDelegate(k,n,o);i.mouseDelegate=true;d.push([m,l,k,i]);j=e.call(b,m,l,i);}else{j=e.apply(b,arguments);}return j;},removeListener:function(l,k,j){var i;if(h[k]){i=a.apply(b,arguments);}else{i=f.apply(b,arguments);}return i;},getListeners:function(p,o){var n=[],r,m=(o==="mouseover"||o==="mouseout"),q,k,j;if(o&&(m||h[o])){r=c.call(b,p,this._getType(o));if(r){for(k=r.length-1;k>-1;k--){j=r[k];q=j.fn.mouseDelegate;if((h[o]&&q)||(m&&!q)){n.push(j);}}}}else{n=c.apply(b,arguments);}return(n&&n.length)?n:null;}},true);b.on=b.addListener;}());YAHOO.register("event-mouseenter",YAHOO.util.Event,{version:"2.9.0",build:"2800"}); \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter.js new file mode 100644 index 0000000..c265487 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-mouseenter/event-mouseenter.js @@ -0,0 +1,218 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +/** + * Augments the Event Utility with support for the mouseenter and mouseleave + * events: A mouseenter event fires the first time the mouse enters an + * element; a mouseleave event first the first time the mouse leaves an + * element. + * + * @module event-mouseenter + * @title Event Utility mouseenter and mouseout Module + * @namespace YAHOO.util + * @requires event + */ + +(function () { + + var Event = YAHOO.util.Event, + Lang = YAHOO.lang, + + addListener = Event.addListener, + removeListener = Event.removeListener, + getListeners = Event.getListeners, + + delegates = [], + + specialTypes = { + mouseenter: "mouseover", + mouseleave: "mouseout" + }, + + remove = function(el, type, fn) { + + var index = Event._getCacheIndex(delegates, el, type, fn), + cacheItem, + returnVal; + + if (index >= 0) { + cacheItem = delegates[index]; + } + + if (el && cacheItem) { + + // removeListener will translate the value of type + returnVal = removeListener.call(Event, cacheItem[0], type, cacheItem[3]); + + if (returnVal) { + delete delegates[index][2]; + delete delegates[index][3]; + delegates.splice(index, 1); + } + + } + + return returnVal; + + }; + + + Lang.augmentObject(Event._specialTypes, specialTypes); + + Lang.augmentObject(Event, { + + /** + * Creates a delegate function used to call mouseover and mouseleave + * event listeners specified via the + * YAHOO.util.Event.addListener + * or YAHOO.util.Event.on method. + * + * @method _createMouseDelegate + * + * @param {Function} fn The method (event listener) to call + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the listener + * @param {Boolean|object} overrideContext If true, the value of the + * obj parameter becomes the execution context + * of the listener. If an object, this object + * becomes the execution context. + * @return {Function} Function that will call the event listener + * specified by either the YAHOO.util.Event.addListener + * or YAHOO.util.Event.on method. + * @private + * @static + * @for Event + */ + _createMouseDelegate: function (fn, obj, overrideContext) { + + return function (event, container) { + + var el = this, + relatedTarget = Event.getRelatedTarget(event), + context, + args; + + if (el != relatedTarget && !YAHOO.util.Dom.isAncestor(el, relatedTarget)) { + + context = el; + + if (overrideContext) { + if (overrideContext === true) { + context = obj; + } else { + context = overrideContext; + } + } + + // The default args passed back to a mouseenter or + // mouseleave listener are: the event, and any object + // the user passed when subscribing + + args = [event, obj]; + + // Add the element and delegation container as arguments + // when delegating mouseenter and mouseleave + + if (container) { + args.splice(1, 0, el, container); + } + + return fn.apply(context, args); + + } + + }; + + }, + + addListener: function (el, type, fn, obj, overrideContext) { + + var fnDelegate, + returnVal; + + if (specialTypes[type]) { + + fnDelegate = Event._createMouseDelegate(fn, obj, overrideContext); + + fnDelegate.mouseDelegate = true; + + delegates.push([el, type, fn, fnDelegate]); + + // addListener will translate the value of type + returnVal = addListener.call(Event, el, type, fnDelegate); + + } + else { + returnVal = addListener.apply(Event, arguments); + } + + return returnVal; + + }, + + removeListener: function (el, type, fn) { + + var returnVal; + + if (specialTypes[type]) { + returnVal = remove.apply(Event, arguments); + } + else { + returnVal = removeListener.apply(Event, arguments); + } + + return returnVal; + + }, + + getListeners: function (el, type) { + + // If the user specified the type as mouseover or mouseout, + // need to filter out those used by mouseenter and mouseleave. + // If the user specified the type as mouseenter or mouseleave, + // need to filter out the true mouseover and mouseout listeners. + + var listeners = [], + elListeners, + bMouseOverOrOut = (type === "mouseover" || type === "mouseout"), + bMouseDelegate, + i, + l; + + if (type && (bMouseOverOrOut || specialTypes[type])) { + + elListeners = getListeners.call(Event, el, this._getType(type)); + + if (elListeners) { + + for (i=elListeners.length-1; i>-1; i--) { + + l = elListeners[i]; + bMouseDelegate = l.fn.mouseDelegate; + + if ((specialTypes[type] && bMouseDelegate) || (bMouseOverOrOut && !bMouseDelegate)) { + listeners.push(l); + } + + } + + } + + } + else { + listeners = getListeners.apply(Event, arguments); + } + + return (listeners && listeners.length) ? listeners : null; + + } + + }, true); + + Event.on = Event.addListener; + +}()); +YAHOO.register("event-mouseenter", YAHOO.util.Event, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-debug.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-debug.js new file mode 100644 index 0000000..46e6b37 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-debug.js @@ -0,0 +1,624 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ + +/** + * DOM event simulation utility + * @module event-simulate + * @namespace YAHOO.util + * @requires yahoo,dom,event + */ + +/** + * The UserAction object provides functions that simulate events occurring in + * the browser. Since these are simulated events, they do not behave exactly + * as regular, user-initiated events do, but can be used to test simple + * user interactions safely. + * + * @namespace YAHOO.util + * @class UserAction + * @static + */ +YAHOO.util.UserAction = { + + //-------------------------------------------------------------------------- + // Generic event methods + //-------------------------------------------------------------------------- + + /** + * Simulates a key event using the given event information to populate + * the generated event object. This method does browser-equalizing + * calculations to account for differences in the DOM and IE event models + * as well as different browser quirks. Note: keydown causes Safari 2.x to + * crash. + * @method simulateKeyEvent + * @private + * @static + * @param {HTMLElement} target The target of the given event. + * @param {String} type The type of event to fire. This can be any one of + * the following: keyup, keydown, and keypress. + * @param {Boolean} bubbles (Optional) Indicates if the event can be + * bubbled up. DOM Level 3 specifies that all key events bubble by + * default. The default is true. + * @param {Boolean} cancelable (Optional) Indicates if the event can be + * canceled using preventDefault(). DOM Level 3 specifies that all + * key events can be cancelled. The default + * is true. + * @param {Window} view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} metaKey (Optional) Indicates if one of the META keys + * is pressed while the event is firing. The default is false. + * @param {int} keyCode (Optional) The code for the key that is in use. + * The default is 0. + * @param {int} charCode (Optional) The Unicode code for the character + * associated with the key being used. The default is 0. + */ + simulateKeyEvent : function (target /*:HTMLElement*/, type /*:String*/, + bubbles /*:Boolean*/, cancelable /*:Boolean*/, + view /*:Window*/, + ctrlKey /*:Boolean*/, altKey /*:Boolean*/, + shiftKey /*:Boolean*/, metaKey /*:Boolean*/, + keyCode /*:int*/, charCode /*:int*/) /*:Void*/ + { + //check target + target = YAHOO.util.Dom.get(target); + if (!target){ + throw new Error("simulateKeyEvent(): Invalid target."); + } + + //check event type + if (YAHOO.lang.isString(type)){ + type = type.toLowerCase(); + switch(type){ + case "keyup": + case "keydown": + case "keypress": + break; + case "textevent": //DOM Level 3 + type = "keypress"; + break; + // @TODO was the fallthrough intentional, if so throw error + default: + throw new Error("simulateKeyEvent(): Event type '" + type + "' not supported."); + } + } else { + throw new Error("simulateKeyEvent(): Event type must be a string."); + } + + //setup default values + if (!YAHOO.lang.isBoolean(bubbles)){ + bubbles = true; //all key events bubble + } + if (!YAHOO.lang.isBoolean(cancelable)){ + cancelable = true; //all key events can be cancelled + } + if (!YAHOO.lang.isObject(view)){ + view = window; //view is typically window + } + if (!YAHOO.lang.isBoolean(ctrlKey)){ + ctrlKey = false; + } + if (!YAHOO.lang.isBoolean(altKey)){ + altKey = false; + } + if (!YAHOO.lang.isBoolean(shiftKey)){ + shiftKey = false; + } + if (!YAHOO.lang.isBoolean(metaKey)){ + metaKey = false; + } + if (!YAHOO.lang.isNumber(keyCode)){ + keyCode = 0; + } + if (!YAHOO.lang.isNumber(charCode)){ + charCode = 0; + } + + //try to create a mouse event + var customEvent /*:MouseEvent*/ = null; + + //check for DOM-compliant browsers first + if (YAHOO.lang.isFunction(document.createEvent)){ + + try { + + //try to create key event + customEvent = document.createEvent("KeyEvents"); + + /* + * Interesting problem: Firefox implemented a non-standard + * version of initKeyEvent() based on DOM Level 2 specs. + * Key event was removed from DOM Level 2 and re-introduced + * in DOM Level 3 with a different interface. Firefox is the + * only browser with any implementation of Key Events, so for + * now, assume it's Firefox if the above line doesn't error. + */ + //TODO: Decipher between Firefox's implementation and a correct one. + customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey, + altKey, shiftKey, metaKey, keyCode, charCode); + + } catch (ex /*:Error*/){ + + /* + * If it got here, that means key events aren't officially supported. + * Safari/WebKit is a real problem now. WebKit 522 won't let you + * set keyCode, charCode, or other properties if you use a + * UIEvent, so we first must try to create a generic event. The + * fun part is that this will throw an error on Safari 2.x. The + * end result is that we need another try...catch statement just to + * deal with this mess. + */ + try { + + //try to create generic event - will fail in Safari 2.x + customEvent = document.createEvent("Events"); + + } catch (uierror /*:Error*/){ + + //the above failed, so create a UIEvent for Safari 2.x + customEvent = document.createEvent("UIEvents"); + + } finally { + + customEvent.initEvent(type, bubbles, cancelable); + + //initialize + customEvent.view = view; + customEvent.altKey = altKey; + customEvent.ctrlKey = ctrlKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + customEvent.keyCode = keyCode; + customEvent.charCode = charCode; + + } + + } + + //fire the event + target.dispatchEvent(customEvent); + + } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE + + //create an IE event object + customEvent = document.createEventObject(); + + //assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + + /* + * IE doesn't support charCode explicitly. CharCode should + * take precedence over any keyCode value for accurate + * representation. + */ + customEvent.keyCode = (charCode > 0) ? charCode : keyCode; + + //fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error("simulateKeyEvent(): No event simulation framework present."); + } + }, + + /** + * Simulates a mouse event using the given event information to populate + * the generated event object. This method does browser-equalizing + * calculations to account for differences in the DOM and IE event models + * as well as different browser quirks. + * @method simulateMouseEvent + * @private + * @static + * @param {HTMLElement} target The target of the given event. + * @param {String} type The type of event to fire. This can be any one of + * the following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Boolean} bubbles (Optional) Indicates if the event can be + * bubbled up. DOM Level 2 specifies that all mouse events bubble by + * default. The default is true. + * @param {Boolean} cancelable (Optional) Indicates if the event can be + * canceled using preventDefault(). DOM Level 2 specifies that all + * mouse events except mousemove can be cancelled. The default + * is true for all events except mousemove, for which the default + * is false. + * @param {Window} view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {int} detail (Optional) The number of times the mouse button has + * been used. The default value is 1. + * @param {int} screenX (Optional) The x-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} screenY (Optional) The y-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} clientX (Optional) The x-coordinate on the client at which + * point the event occured. The default is 0. + * @param {int} clientY (Optional) The y-coordinate on the client at which + * point the event occured. The default is 0. + * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} metaKey (Optional) Indicates if one of the META keys + * is pressed while the event is firing. The default is false. + * @param {int} button (Optional) The button being pressed while the event + * is executing. The value should be 0 for the primary mouse button + * (typically the left button), 1 for the terciary mouse button + * (typically the middle button), and 2 for the secondary mouse button + * (typically the right button). The default is 0. + * @param {HTMLElement} relatedTarget (Optional) For mouseout events, + * this is the element that the mouse has moved to. For mouseover + * events, this is the element that the mouse has moved from. This + * argument is ignored for all other events. The default is null. + */ + simulateMouseEvent : function (target /*:HTMLElement*/, type /*:String*/, + bubbles /*:Boolean*/, cancelable /*:Boolean*/, + view /*:Window*/, detail /*:int*/, + screenX /*:int*/, screenY /*:int*/, + clientX /*:int*/, clientY /*:int*/, + ctrlKey /*:Boolean*/, altKey /*:Boolean*/, + shiftKey /*:Boolean*/, metaKey /*:Boolean*/, + button /*:int*/, relatedTarget /*:HTMLElement*/) /*:Void*/ + { + + //check target + target = YAHOO.util.Dom.get(target); + if (!target){ + throw new Error("simulateMouseEvent(): Invalid target."); + } + + relatedTarget = relatedTarget || null; + + //check event type + if (YAHOO.lang.isString(type)){ + type = type.toLowerCase(); + switch(type){ + case "mouseover": + case "mouseout": + case "mousedown": + case "mouseup": + case "click": + case "dblclick": + case "mousemove": + break; + default: + throw new Error("simulateMouseEvent(): Event type '" + type + "' not supported."); + } + } else { + throw new Error("simulateMouseEvent(): Event type must be a string."); + } + + //setup default values + if (!YAHOO.lang.isBoolean(bubbles)){ + bubbles = true; //all mouse events bubble + } + if (!YAHOO.lang.isBoolean(cancelable)){ + cancelable = (type != "mousemove"); //mousemove is the only one that can't be cancelled + } + if (!YAHOO.lang.isObject(view)){ + view = window; //view is typically window + } + if (!YAHOO.lang.isNumber(detail)){ + detail = 1; //number of mouse clicks must be at least one + } + if (!YAHOO.lang.isNumber(screenX)){ + screenX = 0; + } + if (!YAHOO.lang.isNumber(screenY)){ + screenY = 0; + } + if (!YAHOO.lang.isNumber(clientX)){ + clientX = 0; + } + if (!YAHOO.lang.isNumber(clientY)){ + clientY = 0; + } + if (!YAHOO.lang.isBoolean(ctrlKey)){ + ctrlKey = false; + } + if (!YAHOO.lang.isBoolean(altKey)){ + altKey = false; + } + if (!YAHOO.lang.isBoolean(shiftKey)){ + shiftKey = false; + } + if (!YAHOO.lang.isBoolean(metaKey)){ + metaKey = false; + } + if (!YAHOO.lang.isNumber(button)){ + button = 0; + } + + //try to create a mouse event + var customEvent /*:MouseEvent*/ = null; + + //check for DOM-compliant browsers first + if (YAHOO.lang.isFunction(document.createEvent)){ + + customEvent = document.createEvent("MouseEvents"); + + //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent() + if (customEvent.initMouseEvent){ + customEvent.initMouseEvent(type, bubbles, cancelable, view, detail, + screenX, screenY, clientX, clientY, + ctrlKey, altKey, shiftKey, metaKey, + button, relatedTarget); + } else { //Safari + + //the closest thing available in Safari 2.x is UIEvents + customEvent = document.createEvent("UIEvents"); + customEvent.initEvent(type, bubbles, cancelable); + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + customEvent.button = button; + customEvent.relatedTarget = relatedTarget; + } + + /* + * Check to see if relatedTarget has been assigned. Firefox + * versions less than 2.0 don't allow it to be assigned via + * initMouseEvent() and the property is readonly after event + * creation, so in order to keep YAHOO.util.getRelatedTarget() + * working, assign to the IE proprietary toElement property + * for mouseout event and fromElement property for mouseover + * event. + */ + if (relatedTarget && !customEvent.relatedTarget){ + if (type == "mouseout"){ + customEvent.toElement = relatedTarget; + } else if (type == "mouseover"){ + customEvent.fromElement = relatedTarget; + } + } + + //fire the event + target.dispatchEvent(customEvent); + + } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE + + //create an IE event object + customEvent = document.createEventObject(); + + //assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + + //fix button property for IE's wacky implementation + switch(button){ + case 0: + customEvent.button = 1; + break; + case 1: + customEvent.button = 4; + break; + case 2: + //leave as is + break; + default: + customEvent.button = 0; + } + + /* + * Have to use relatedTarget because IE won't allow assignment + * to toElement or fromElement on generic events. This keeps + * YAHOO.util.customEvent.getRelatedTarget() functional. + */ + customEvent.relatedTarget = relatedTarget; + + //fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error("simulateMouseEvent(): No event simulation framework present."); + } + }, + + //-------------------------------------------------------------------------- + // Mouse events + //-------------------------------------------------------------------------- + + /** + * Simulates a mouse event on a particular element. + * @param {HTMLElement} target The element to click on. + * @param {String} type The type of event to fire. This can be any one of + * the following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseEvent + * @static + */ + fireMouseEvent : function (target /*:HTMLElement*/, type /*:String*/, + options /*:Object*/) /*:Void*/ + { + options = options || {}; + this.simulateMouseEvent(target, type, options.bubbles, + options.cancelable, options.view, options.detail, options.screenX, + options.screenY, options.clientX, options.clientY, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, options.button, + options.relatedTarget); + }, + + /** + * Simulates a click on a particular element. + * @param {HTMLElement} target The element to click on. + * @param {Object} options Additional event options (use DOM standard names). + * @method click + * @static + */ + click : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireMouseEvent(target, "click", options); + }, + + /** + * Simulates a double click on a particular element. + * @param {HTMLElement} target The element to double click on. + * @param {Object} options Additional event options (use DOM standard names). + * @method dblclick + * @static + */ + dblclick : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireMouseEvent( target, "dblclick", options); + }, + + /** + * Simulates a mousedown on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mousedown + * @static + */ + mousedown : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mousedown", options); + }, + + /** + * Simulates a mousemove on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mousemove + * @static + */ + mousemove : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mousemove", options); + }, + + /** + * Simulates a mouseout event on a particular element. Use "relatedTarget" + * on the options object to specify where the mouse moved to. + * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so + * toElement is assigned in its place. IE doesn't allow toElement to be + * be assigned, so relatedTarget is assigned in its place. Both of these + * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly + * in both browsers. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseout + * @static + */ + mouseout : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mouseout", options); + }, + + /** + * Simulates a mouseover event on a particular element. Use "relatedTarget" + * on the options object to specify where the mouse moved from. + * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so + * fromElement is assigned in its place. IE doesn't allow fromElement to be + * be assigned, so relatedTarget is assigned in its place. Both of these + * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly + * in both browsers. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseover + * @static + */ + mouseover : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mouseover", options); + }, + + /** + * Simulates a mouseup on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseup + * @static + */ + mouseup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mouseup", options); + }, + + //-------------------------------------------------------------------------- + // Key events + //-------------------------------------------------------------------------- + + /** + * Fires an event that normally would be fired by the keyboard (keyup, + * keydown, keypress). Make sure to specify either keyCode or charCode as + * an option. + * @private + * @param {String} type The type of event ("keyup", "keydown" or "keypress"). + * @param {HTMLElement} target The target of the event. + * @param {Object} options Options for the event. Either keyCode or charCode + * are required. + * @method fireKeyEvent + * @static + */ + fireKeyEvent : function (type /*:String*/, target /*:HTMLElement*/, + options /*:Object*/) /*:Void*/ + { + options = options || {}; + this.simulateKeyEvent(target, type, options.bubbles, + options.cancelable, options.view, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, + options.keyCode, options.charCode); + }, + + /** + * Simulates a keydown event on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method keydown + * @static + */ + keydown : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireKeyEvent("keydown", target, options); + }, + + /** + * Simulates a keypress on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method keypress + * @static + */ + keypress : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireKeyEvent("keypress", target, options); + }, + + /** + * Simulates a keyup event on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method keyup + * @static + */ + keyup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireKeyEvent("keyup", target, options); + } + + +}; +YAHOO.register("event-simulate", YAHOO.util.UserAction, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-min.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-min.js new file mode 100644 index 0000000..63b9710 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate-min.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +YAHOO.util.UserAction={simulateKeyEvent:function(f,j,e,c,l,b,a,k,h,n,m){f=YAHOO.util.Dom.get(f);if(!f){throw new Error("simulateKeyEvent(): Invalid target.");}if(YAHOO.lang.isString(j)){j=j.toLowerCase();switch(j){case"keyup":case"keydown":case"keypress":break;case"textevent":j="keypress";break;default:throw new Error("simulateKeyEvent(): Event type '"+j+"' not supported.");}}else{throw new Error("simulateKeyEvent(): Event type must be a string.");}if(!YAHOO.lang.isBoolean(e)){e=true;}if(!YAHOO.lang.isBoolean(c)){c=true;}if(!YAHOO.lang.isObject(l)){l=window;}if(!YAHOO.lang.isBoolean(b)){b=false;}if(!YAHOO.lang.isBoolean(a)){a=false;}if(!YAHOO.lang.isBoolean(k)){k=false;}if(!YAHOO.lang.isBoolean(h)){h=false;}if(!YAHOO.lang.isNumber(n)){n=0;}if(!YAHOO.lang.isNumber(m)){m=0;}var i=null;if(YAHOO.lang.isFunction(document.createEvent)){try{i=document.createEvent("KeyEvents");i.initKeyEvent(j,e,c,l,b,a,k,h,n,m);}catch(g){try{i=document.createEvent("Events");}catch(d){i=document.createEvent("UIEvents");}finally{i.initEvent(j,e,c);i.view=l;i.altKey=a;i.ctrlKey=b;i.shiftKey=k;i.metaKey=h;i.keyCode=n;i.charCode=m;}}f.dispatchEvent(i);}else{if(YAHOO.lang.isObject(document.createEventObject)){i=document.createEventObject();i.bubbles=e;i.cancelable=c;i.view=l;i.ctrlKey=b;i.altKey=a;i.shiftKey=k;i.metaKey=h;i.keyCode=(m>0)?m:n;f.fireEvent("on"+j,i);}else{throw new Error("simulateKeyEvent(): No event simulation framework present.");}}},simulateMouseEvent:function(k,p,h,e,q,j,g,f,d,b,c,a,o,m,i,l){k=YAHOO.util.Dom.get(k);if(!k){throw new Error("simulateMouseEvent(): Invalid target.");}l=l||null;if(YAHOO.lang.isString(p)){p=p.toLowerCase();switch(p){case"mouseover":case"mouseout":case"mousedown":case"mouseup":case"click":case"dblclick":case"mousemove":break;default:throw new Error("simulateMouseEvent(): Event type '"+p+"' not supported.");}}else{throw new Error("simulateMouseEvent(): Event type must be a string.");}if(!YAHOO.lang.isBoolean(h)){h=true;}if(!YAHOO.lang.isBoolean(e)){e=(p!="mousemove");}if(!YAHOO.lang.isObject(q)){q=window;}if(!YAHOO.lang.isNumber(j)){j=1;}if(!YAHOO.lang.isNumber(g)){g=0;}if(!YAHOO.lang.isNumber(f)){f=0;}if(!YAHOO.lang.isNumber(d)){d=0;}if(!YAHOO.lang.isNumber(b)){b=0;}if(!YAHOO.lang.isBoolean(c)){c=false;}if(!YAHOO.lang.isBoolean(a)){a=false;}if(!YAHOO.lang.isBoolean(o)){o=false;}if(!YAHOO.lang.isBoolean(m)){m=false;}if(!YAHOO.lang.isNumber(i)){i=0;}var n=null;if(YAHOO.lang.isFunction(document.createEvent)){n=document.createEvent("MouseEvents");if(n.initMouseEvent){n.initMouseEvent(p,h,e,q,j,g,f,d,b,c,a,o,m,i,l);}else{n=document.createEvent("UIEvents");n.initEvent(p,h,e);n.view=q;n.detail=j;n.screenX=g;n.screenY=f;n.clientX=d;n.clientY=b;n.ctrlKey=c;n.altKey=a;n.metaKey=m;n.shiftKey=o;n.button=i;n.relatedTarget=l;}if(l&&!n.relatedTarget){if(p=="mouseout"){n.toElement=l;}else{if(p=="mouseover"){n.fromElement=l;}}}k.dispatchEvent(n);}else{if(YAHOO.lang.isObject(document.createEventObject)){n=document.createEventObject();n.bubbles=h;n.cancelable=e;n.view=q;n.detail=j;n.screenX=g;n.screenY=f;n.clientX=d;n.clientY=b;n.ctrlKey=c;n.altKey=a;n.metaKey=m;n.shiftKey=o;switch(i){case 0:n.button=1;break;case 1:n.button=4;break;case 2:break;default:n.button=0;}n.relatedTarget=l;k.fireEvent("on"+p,n);}else{throw new Error("simulateMouseEvent(): No event simulation framework present.");}}},fireMouseEvent:function(c,b,a){a=a||{};this.simulateMouseEvent(c,b,a.bubbles,a.cancelable,a.view,a.detail,a.screenX,a.screenY,a.clientX,a.clientY,a.ctrlKey,a.altKey,a.shiftKey,a.metaKey,a.button,a.relatedTarget);},click:function(b,a){this.fireMouseEvent(b,"click",a);},dblclick:function(b,a){this.fireMouseEvent(b,"dblclick",a);},mousedown:function(b,a){this.fireMouseEvent(b,"mousedown",a);},mousemove:function(b,a){this.fireMouseEvent(b,"mousemove",a);},mouseout:function(b,a){this.fireMouseEvent(b,"mouseout",a);},mouseover:function(b,a){this.fireMouseEvent(b,"mouseover",a);},mouseup:function(b,a){this.fireMouseEvent(b,"mouseup",a);},fireKeyEvent:function(b,c,a){a=a||{};this.simulateKeyEvent(c,b,a.bubbles,a.cancelable,a.view,a.ctrlKey,a.altKey,a.shiftKey,a.metaKey,a.keyCode,a.charCode);},keydown:function(b,a){this.fireKeyEvent("keydown",b,a);},keypress:function(b,a){this.fireKeyEvent("keypress",b,a);},keyup:function(b,a){this.fireKeyEvent("keyup",b,a);}};YAHOO.register("event-simulate",YAHOO.util.UserAction,{version:"2.9.0",build:"2800"}); \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate.js new file mode 100644 index 0000000..46e6b37 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event-simulate/event-simulate.js @@ -0,0 +1,624 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ + +/** + * DOM event simulation utility + * @module event-simulate + * @namespace YAHOO.util + * @requires yahoo,dom,event + */ + +/** + * The UserAction object provides functions that simulate events occurring in + * the browser. Since these are simulated events, they do not behave exactly + * as regular, user-initiated events do, but can be used to test simple + * user interactions safely. + * + * @namespace YAHOO.util + * @class UserAction + * @static + */ +YAHOO.util.UserAction = { + + //-------------------------------------------------------------------------- + // Generic event methods + //-------------------------------------------------------------------------- + + /** + * Simulates a key event using the given event information to populate + * the generated event object. This method does browser-equalizing + * calculations to account for differences in the DOM and IE event models + * as well as different browser quirks. Note: keydown causes Safari 2.x to + * crash. + * @method simulateKeyEvent + * @private + * @static + * @param {HTMLElement} target The target of the given event. + * @param {String} type The type of event to fire. This can be any one of + * the following: keyup, keydown, and keypress. + * @param {Boolean} bubbles (Optional) Indicates if the event can be + * bubbled up. DOM Level 3 specifies that all key events bubble by + * default. The default is true. + * @param {Boolean} cancelable (Optional) Indicates if the event can be + * canceled using preventDefault(). DOM Level 3 specifies that all + * key events can be cancelled. The default + * is true. + * @param {Window} view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} metaKey (Optional) Indicates if one of the META keys + * is pressed while the event is firing. The default is false. + * @param {int} keyCode (Optional) The code for the key that is in use. + * The default is 0. + * @param {int} charCode (Optional) The Unicode code for the character + * associated with the key being used. The default is 0. + */ + simulateKeyEvent : function (target /*:HTMLElement*/, type /*:String*/, + bubbles /*:Boolean*/, cancelable /*:Boolean*/, + view /*:Window*/, + ctrlKey /*:Boolean*/, altKey /*:Boolean*/, + shiftKey /*:Boolean*/, metaKey /*:Boolean*/, + keyCode /*:int*/, charCode /*:int*/) /*:Void*/ + { + //check target + target = YAHOO.util.Dom.get(target); + if (!target){ + throw new Error("simulateKeyEvent(): Invalid target."); + } + + //check event type + if (YAHOO.lang.isString(type)){ + type = type.toLowerCase(); + switch(type){ + case "keyup": + case "keydown": + case "keypress": + break; + case "textevent": //DOM Level 3 + type = "keypress"; + break; + // @TODO was the fallthrough intentional, if so throw error + default: + throw new Error("simulateKeyEvent(): Event type '" + type + "' not supported."); + } + } else { + throw new Error("simulateKeyEvent(): Event type must be a string."); + } + + //setup default values + if (!YAHOO.lang.isBoolean(bubbles)){ + bubbles = true; //all key events bubble + } + if (!YAHOO.lang.isBoolean(cancelable)){ + cancelable = true; //all key events can be cancelled + } + if (!YAHOO.lang.isObject(view)){ + view = window; //view is typically window + } + if (!YAHOO.lang.isBoolean(ctrlKey)){ + ctrlKey = false; + } + if (!YAHOO.lang.isBoolean(altKey)){ + altKey = false; + } + if (!YAHOO.lang.isBoolean(shiftKey)){ + shiftKey = false; + } + if (!YAHOO.lang.isBoolean(metaKey)){ + metaKey = false; + } + if (!YAHOO.lang.isNumber(keyCode)){ + keyCode = 0; + } + if (!YAHOO.lang.isNumber(charCode)){ + charCode = 0; + } + + //try to create a mouse event + var customEvent /*:MouseEvent*/ = null; + + //check for DOM-compliant browsers first + if (YAHOO.lang.isFunction(document.createEvent)){ + + try { + + //try to create key event + customEvent = document.createEvent("KeyEvents"); + + /* + * Interesting problem: Firefox implemented a non-standard + * version of initKeyEvent() based on DOM Level 2 specs. + * Key event was removed from DOM Level 2 and re-introduced + * in DOM Level 3 with a different interface. Firefox is the + * only browser with any implementation of Key Events, so for + * now, assume it's Firefox if the above line doesn't error. + */ + //TODO: Decipher between Firefox's implementation and a correct one. + customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey, + altKey, shiftKey, metaKey, keyCode, charCode); + + } catch (ex /*:Error*/){ + + /* + * If it got here, that means key events aren't officially supported. + * Safari/WebKit is a real problem now. WebKit 522 won't let you + * set keyCode, charCode, or other properties if you use a + * UIEvent, so we first must try to create a generic event. The + * fun part is that this will throw an error on Safari 2.x. The + * end result is that we need another try...catch statement just to + * deal with this mess. + */ + try { + + //try to create generic event - will fail in Safari 2.x + customEvent = document.createEvent("Events"); + + } catch (uierror /*:Error*/){ + + //the above failed, so create a UIEvent for Safari 2.x + customEvent = document.createEvent("UIEvents"); + + } finally { + + customEvent.initEvent(type, bubbles, cancelable); + + //initialize + customEvent.view = view; + customEvent.altKey = altKey; + customEvent.ctrlKey = ctrlKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + customEvent.keyCode = keyCode; + customEvent.charCode = charCode; + + } + + } + + //fire the event + target.dispatchEvent(customEvent); + + } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE + + //create an IE event object + customEvent = document.createEventObject(); + + //assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + + /* + * IE doesn't support charCode explicitly. CharCode should + * take precedence over any keyCode value for accurate + * representation. + */ + customEvent.keyCode = (charCode > 0) ? charCode : keyCode; + + //fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error("simulateKeyEvent(): No event simulation framework present."); + } + }, + + /** + * Simulates a mouse event using the given event information to populate + * the generated event object. This method does browser-equalizing + * calculations to account for differences in the DOM and IE event models + * as well as different browser quirks. + * @method simulateMouseEvent + * @private + * @static + * @param {HTMLElement} target The target of the given event. + * @param {String} type The type of event to fire. This can be any one of + * the following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Boolean} bubbles (Optional) Indicates if the event can be + * bubbled up. DOM Level 2 specifies that all mouse events bubble by + * default. The default is true. + * @param {Boolean} cancelable (Optional) Indicates if the event can be + * canceled using preventDefault(). DOM Level 2 specifies that all + * mouse events except mousemove can be cancelled. The default + * is true for all events except mousemove, for which the default + * is false. + * @param {Window} view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {int} detail (Optional) The number of times the mouse button has + * been used. The default value is 1. + * @param {int} screenX (Optional) The x-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} screenY (Optional) The y-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} clientX (Optional) The x-coordinate on the client at which + * point the event occured. The default is 0. + * @param {int} clientY (Optional) The y-coordinate on the client at which + * point the event occured. The default is 0. + * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} metaKey (Optional) Indicates if one of the META keys + * is pressed while the event is firing. The default is false. + * @param {int} button (Optional) The button being pressed while the event + * is executing. The value should be 0 for the primary mouse button + * (typically the left button), 1 for the terciary mouse button + * (typically the middle button), and 2 for the secondary mouse button + * (typically the right button). The default is 0. + * @param {HTMLElement} relatedTarget (Optional) For mouseout events, + * this is the element that the mouse has moved to. For mouseover + * events, this is the element that the mouse has moved from. This + * argument is ignored for all other events. The default is null. + */ + simulateMouseEvent : function (target /*:HTMLElement*/, type /*:String*/, + bubbles /*:Boolean*/, cancelable /*:Boolean*/, + view /*:Window*/, detail /*:int*/, + screenX /*:int*/, screenY /*:int*/, + clientX /*:int*/, clientY /*:int*/, + ctrlKey /*:Boolean*/, altKey /*:Boolean*/, + shiftKey /*:Boolean*/, metaKey /*:Boolean*/, + button /*:int*/, relatedTarget /*:HTMLElement*/) /*:Void*/ + { + + //check target + target = YAHOO.util.Dom.get(target); + if (!target){ + throw new Error("simulateMouseEvent(): Invalid target."); + } + + relatedTarget = relatedTarget || null; + + //check event type + if (YAHOO.lang.isString(type)){ + type = type.toLowerCase(); + switch(type){ + case "mouseover": + case "mouseout": + case "mousedown": + case "mouseup": + case "click": + case "dblclick": + case "mousemove": + break; + default: + throw new Error("simulateMouseEvent(): Event type '" + type + "' not supported."); + } + } else { + throw new Error("simulateMouseEvent(): Event type must be a string."); + } + + //setup default values + if (!YAHOO.lang.isBoolean(bubbles)){ + bubbles = true; //all mouse events bubble + } + if (!YAHOO.lang.isBoolean(cancelable)){ + cancelable = (type != "mousemove"); //mousemove is the only one that can't be cancelled + } + if (!YAHOO.lang.isObject(view)){ + view = window; //view is typically window + } + if (!YAHOO.lang.isNumber(detail)){ + detail = 1; //number of mouse clicks must be at least one + } + if (!YAHOO.lang.isNumber(screenX)){ + screenX = 0; + } + if (!YAHOO.lang.isNumber(screenY)){ + screenY = 0; + } + if (!YAHOO.lang.isNumber(clientX)){ + clientX = 0; + } + if (!YAHOO.lang.isNumber(clientY)){ + clientY = 0; + } + if (!YAHOO.lang.isBoolean(ctrlKey)){ + ctrlKey = false; + } + if (!YAHOO.lang.isBoolean(altKey)){ + altKey = false; + } + if (!YAHOO.lang.isBoolean(shiftKey)){ + shiftKey = false; + } + if (!YAHOO.lang.isBoolean(metaKey)){ + metaKey = false; + } + if (!YAHOO.lang.isNumber(button)){ + button = 0; + } + + //try to create a mouse event + var customEvent /*:MouseEvent*/ = null; + + //check for DOM-compliant browsers first + if (YAHOO.lang.isFunction(document.createEvent)){ + + customEvent = document.createEvent("MouseEvents"); + + //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent() + if (customEvent.initMouseEvent){ + customEvent.initMouseEvent(type, bubbles, cancelable, view, detail, + screenX, screenY, clientX, clientY, + ctrlKey, altKey, shiftKey, metaKey, + button, relatedTarget); + } else { //Safari + + //the closest thing available in Safari 2.x is UIEvents + customEvent = document.createEvent("UIEvents"); + customEvent.initEvent(type, bubbles, cancelable); + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + customEvent.button = button; + customEvent.relatedTarget = relatedTarget; + } + + /* + * Check to see if relatedTarget has been assigned. Firefox + * versions less than 2.0 don't allow it to be assigned via + * initMouseEvent() and the property is readonly after event + * creation, so in order to keep YAHOO.util.getRelatedTarget() + * working, assign to the IE proprietary toElement property + * for mouseout event and fromElement property for mouseover + * event. + */ + if (relatedTarget && !customEvent.relatedTarget){ + if (type == "mouseout"){ + customEvent.toElement = relatedTarget; + } else if (type == "mouseover"){ + customEvent.fromElement = relatedTarget; + } + } + + //fire the event + target.dispatchEvent(customEvent); + + } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE + + //create an IE event object + customEvent = document.createEventObject(); + + //assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + + //fix button property for IE's wacky implementation + switch(button){ + case 0: + customEvent.button = 1; + break; + case 1: + customEvent.button = 4; + break; + case 2: + //leave as is + break; + default: + customEvent.button = 0; + } + + /* + * Have to use relatedTarget because IE won't allow assignment + * to toElement or fromElement on generic events. This keeps + * YAHOO.util.customEvent.getRelatedTarget() functional. + */ + customEvent.relatedTarget = relatedTarget; + + //fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error("simulateMouseEvent(): No event simulation framework present."); + } + }, + + //-------------------------------------------------------------------------- + // Mouse events + //-------------------------------------------------------------------------- + + /** + * Simulates a mouse event on a particular element. + * @param {HTMLElement} target The element to click on. + * @param {String} type The type of event to fire. This can be any one of + * the following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseEvent + * @static + */ + fireMouseEvent : function (target /*:HTMLElement*/, type /*:String*/, + options /*:Object*/) /*:Void*/ + { + options = options || {}; + this.simulateMouseEvent(target, type, options.bubbles, + options.cancelable, options.view, options.detail, options.screenX, + options.screenY, options.clientX, options.clientY, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, options.button, + options.relatedTarget); + }, + + /** + * Simulates a click on a particular element. + * @param {HTMLElement} target The element to click on. + * @param {Object} options Additional event options (use DOM standard names). + * @method click + * @static + */ + click : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireMouseEvent(target, "click", options); + }, + + /** + * Simulates a double click on a particular element. + * @param {HTMLElement} target The element to double click on. + * @param {Object} options Additional event options (use DOM standard names). + * @method dblclick + * @static + */ + dblclick : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireMouseEvent( target, "dblclick", options); + }, + + /** + * Simulates a mousedown on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mousedown + * @static + */ + mousedown : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mousedown", options); + }, + + /** + * Simulates a mousemove on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mousemove + * @static + */ + mousemove : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mousemove", options); + }, + + /** + * Simulates a mouseout event on a particular element. Use "relatedTarget" + * on the options object to specify where the mouse moved to. + * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so + * toElement is assigned in its place. IE doesn't allow toElement to be + * be assigned, so relatedTarget is assigned in its place. Both of these + * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly + * in both browsers. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseout + * @static + */ + mouseout : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mouseout", options); + }, + + /** + * Simulates a mouseover event on a particular element. Use "relatedTarget" + * on the options object to specify where the mouse moved from. + * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so + * fromElement is assigned in its place. IE doesn't allow fromElement to be + * be assigned, so relatedTarget is assigned in its place. Both of these + * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly + * in both browsers. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseover + * @static + */ + mouseover : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mouseover", options); + }, + + /** + * Simulates a mouseup on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method mouseup + * @static + */ + mouseup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireMouseEvent(target, "mouseup", options); + }, + + //-------------------------------------------------------------------------- + // Key events + //-------------------------------------------------------------------------- + + /** + * Fires an event that normally would be fired by the keyboard (keyup, + * keydown, keypress). Make sure to specify either keyCode or charCode as + * an option. + * @private + * @param {String} type The type of event ("keyup", "keydown" or "keypress"). + * @param {HTMLElement} target The target of the event. + * @param {Object} options Options for the event. Either keyCode or charCode + * are required. + * @method fireKeyEvent + * @static + */ + fireKeyEvent : function (type /*:String*/, target /*:HTMLElement*/, + options /*:Object*/) /*:Void*/ + { + options = options || {}; + this.simulateKeyEvent(target, type, options.bubbles, + options.cancelable, options.view, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, + options.keyCode, options.charCode); + }, + + /** + * Simulates a keydown event on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method keydown + * @static + */ + keydown : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireKeyEvent("keydown", target, options); + }, + + /** + * Simulates a keypress on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method keypress + * @static + */ + keypress : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ { + this.fireKeyEvent("keypress", target, options); + }, + + /** + * Simulates a keyup event on a particular element. + * @param {HTMLElement} target The element to act on. + * @param {Object} options Additional event options (use DOM standard names). + * @method keyup + * @static + */ + keyup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ { + this.fireKeyEvent("keyup", target, options); + } + + +}; +YAHOO.register("event-simulate", YAHOO.util.UserAction, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event/event-debug.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event/event-debug.js new file mode 100644 index 0000000..3a5c7e5 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/event/event-debug.js @@ -0,0 +1,2561 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ + +/** + * The CustomEvent class lets you define events for your application + * that can be subscribed to by one or more independent component. + * + * @param {String} type The type of event, which is passed to the callback + * when the event fires + * @param {Object} context The context the event will fire from. "this" will + * refer to this object in the callback. Default value: + * the window object. The listener can override this. + * @param {boolean} silent pass true to prevent the event from writing to + * the debugsystem + * @param {int} signature the signature that the custom event subscriber + * will receive. YAHOO.util.CustomEvent.LIST or + * YAHOO.util.CustomEvent.FLAT. The default is + * YAHOO.util.CustomEvent.LIST. + * @param fireOnce {boolean} If configured to fire once, the custom event + * will only notify subscribers a single time regardless of how many times + * the event is fired. In addition, new subscribers will be notified + * immediately if the event has already been fired. + * @namespace YAHOO.util + * @class CustomEvent + * @constructor + */ +YAHOO.util.CustomEvent = function(type, context, silent, signature, fireOnce) { + + /** + * The type of event, returned to subscribers when the event fires + * @property type + * @type string + */ + this.type = type; + + /** + * The context the event will fire from by default. Defaults to the window obj. + * @property scope + * @type object + */ + this.scope = context || window; + + /** + * By default all custom events are logged in the debug build. Set silent to true + * to disable debug output for this event. + * @property silent + * @type boolean + */ + this.silent = silent; + + /** + * If configured to fire once, the custom event will only notify subscribers + * a single time regardless of how many times the event is fired. In addition, + * new subscribers will be notified immediately if the event has already been + * fired. + * @property fireOnce + * @type boolean + * @default false + */ + this.fireOnce = fireOnce; + + /** + * Indicates whether or not this event has ever been fired. + * @property fired + * @type boolean + * @default false + */ + this.fired = false; + + /** + * For fireOnce events the arguments the event was fired with are stored + * so that new subscribers get the proper payload. + * @property firedWith + * @type Array + */ + this.firedWith = null; + + /** + * Custom events support two styles of arguments provided to the event + * subscribers. + *

    + *
  • YAHOO.util.CustomEvent.LIST: + *
      + *
    • param1: event name
    • + *
    • param2: array of arguments sent to fire
    • + *
    • param3: a custom object supplied by the subscriber
    • + *
    + *
  • + *
  • YAHOO.util.CustomEvent.FLAT + *
      + *
    • param1: the first argument passed to fire. If you need to + * pass multiple parameters, use and array or object literal
    • + *
    • param2: a custom object supplied by the subscriber
    • + *
    + *
  • + *
+ * @property signature + * @type int + */ + this.signature = signature || YAHOO.util.CustomEvent.LIST; + + /** + * The subscribers to this event + * @property subscribers + * @type Subscriber[] + */ + this.subscribers = []; + + if (!this.silent) { + YAHOO.log( "Creating " + this, "info", "Event" ); + } + + var onsubscribeType = "_YUICEOnSubscribe"; + + // Only add subscribe events for events that are not generated by + // CustomEvent + if (type !== onsubscribeType) { + + /** + * Custom events provide a custom event that fires whenever there is + * a new subscriber to the event. This provides an opportunity to + * handle the case where there is a non-repeating event that has + * already fired has a new subscriber. + * + * @event subscribeEvent + * @type YAHOO.util.CustomEvent + * @param fn {Function} The function to execute + * @param obj An object to be passed along when the event fires. + * Defaults to the custom event. + * @param override If true, the obj passed in becomes the + * execution context of the listener. If an object, that object becomes + * the execution context. Defaults to the custom event. + */ + this.subscribeEvent = + new YAHOO.util.CustomEvent(onsubscribeType, this, true); + + } + + + /** + * In order to make it possible to execute the rest of the subscriber + * stack when one thows an exception, the subscribers exceptions are + * caught. The most recent exception is stored in this property + * @property lastError + * @type Error + */ + this.lastError = null; +}; + +/** + * Subscriber listener sigature constant. The LIST type returns three + * parameters: the event type, the array of args passed to fire, and + * the optional custom object + * @property YAHOO.util.CustomEvent.LIST + * @static + * @type int + */ +YAHOO.util.CustomEvent.LIST = 0; + +/** + * Subscriber listener sigature constant. The FLAT type returns two + * parameters: the first argument passed to fire and the optional + * custom object + * @property YAHOO.util.CustomEvent.FLAT + * @static + * @type int + */ +YAHOO.util.CustomEvent.FLAT = 1; + +YAHOO.util.CustomEvent.prototype = { + + /** + * Subscribes the caller to this event + * @method subscribe + * @param {Function} fn The function to execute + * @param {Object} obj An object to be passed along when the event + * fires. + * @param {boolean|Object} overrideContext If true, the obj passed in + * becomes the execution. + * context of the listener. If an object, that object becomes the execution + * context. + */ + subscribe: function(fn, obj, overrideContext) { + + if (!fn) { +throw new Error("Invalid callback for subscriber to '" + this.type + "'"); + } + + if (this.subscribeEvent) { + this.subscribeEvent.fire(fn, obj, overrideContext); + } + + var s = new YAHOO.util.Subscriber(fn, obj, overrideContext); + + if (this.fireOnce && this.fired) { + this.notify(s, this.firedWith); + } else { + this.subscribers.push(s); + } + }, + + /** + * Unsubscribes subscribers. + * @method unsubscribe + * @param {Function} fn The subscribed function to remove, if not supplied + * all will be removed + * @param {Object} obj The custom object passed to subscribe. This is + * optional, but if supplied will be used to + * disambiguate multiple listeners that are the same + * (e.g., you subscribe many object using a function + * that lives on the prototype) + * @return {boolean} True if the subscriber was found and detached. + */ + unsubscribe: function(fn, obj) { + + if (!fn) { + return this.unsubscribeAll(); + } + + var found = false; + for (var i=0, len=this.subscribers.length; i + *
  • The type of event
  • + *
  • All of the arguments fire() was executed with as an array
  • + *
  • The custom object (if any) that was passed into the subscribe() + * method
  • + * + * @method fire + * @param {Object*} arguments an arbitrary set of parameters to pass to + * the handler. + * @return {boolean} false if one of the subscribers returned false, + * true otherwise + */ + fire: function() { + + this.lastError = null; + + var errors = [], + len=this.subscribers.length; + + + var args=[].slice.call(arguments, 0), ret=true, i, rebuild=false; + + if (this.fireOnce) { + if (this.fired) { + YAHOO.log('fireOnce event has already fired: ' + this.type); + return true; + } else { + this.firedWith = args; + } + } + + this.fired = true; + + if (!len && this.silent) { + //YAHOO.log('DEBUG no subscribers'); + return true; + } + + if (!this.silent) { + YAHOO.log( "Firing " + this + ", " + + "args: " + args + ", " + + "subscribers: " + len, + "info", "Event" ); + } + + // make a copy of the subscribers so that there are + // no index problems if one subscriber removes another. + var subs = this.subscribers.slice(); + + for (i=0; i " + s, "info", "Event" ); + } + + if (this.signature == YAHOO.util.CustomEvent.FLAT) { + + if (args.length > 0) { + param = args[0]; + } + + try { + ret = s.fn.call(scope, param, s.obj); + } catch(e) { + this.lastError = e; + // errors.push(e); + YAHOO.log(this + " subscriber exception: " + e, "error", "Event"); + if (throwErrors) { + throw e; + } + } + } else { + try { + ret = s.fn.call(scope, this.type, args, s.obj); + } catch(ex) { + this.lastError = ex; + YAHOO.log(this + " subscriber exception: " + ex, "error", "Event"); + if (throwErrors) { + throw ex; + } + } + } + + return ret; + }, + + /** + * Removes all listeners + * @method unsubscribeAll + * @return {int} The number of listeners unsubscribed + */ + unsubscribeAll: function() { + var l = this.subscribers.length, i; + for (i=l-1; i>-1; i--) { + this._delete(i); + } + + this.subscribers=[]; + + return l; + }, + + /** + * @method _delete + * @private + */ + _delete: function(index) { + var s = this.subscribers[index]; + if (s) { + delete s.fn; + delete s.obj; + } + + // this.subscribers[index]=null; + this.subscribers.splice(index, 1); + }, + + /** + * @method toString + */ + toString: function() { + return "CustomEvent: " + "'" + this.type + "', " + + "context: " + this.scope; + + } +}; + +///////////////////////////////////////////////////////////////////// + +/** + * Stores the subscriber information to be used when the event fires. + * @param {Function} fn The function to execute + * @param {Object} obj An object to be passed along when the event fires + * @param {boolean} overrideContext If true, the obj passed in becomes the execution + * context of the listener + * @class Subscriber + * @constructor + */ +YAHOO.util.Subscriber = function(fn, obj, overrideContext) { + + /** + * The callback that will be execute when the event fires + * @property fn + * @type function + */ + this.fn = fn; + + /** + * An optional custom object that will passed to the callback when + * the event fires + * @property obj + * @type object + */ + this.obj = YAHOO.lang.isUndefined(obj) ? null : obj; + + /** + * The default execution context for the event listener is defined when the + * event is created (usually the object which contains the event). + * By setting overrideContext to true, the execution context becomes the custom + * object passed in by the subscriber. If overrideContext is an object, that + * object becomes the context. + * @property overrideContext + * @type boolean|object + */ + this.overrideContext = overrideContext; + +}; + +/** + * Returns the execution context for this listener. If overrideContext was set to true + * the custom obj will be the context. If overrideContext is an object, that is the + * context, otherwise the default context will be used. + * @method getScope + * @param {Object} defaultScope the context to use if this listener does not + * override it. + */ +YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) { + if (this.overrideContext) { + if (this.overrideContext === true) { + return this.obj; + } else { + return this.overrideContext; + } + } + return defaultScope; +}; + +/** + * Returns true if the fn and obj match this objects properties. + * Used by the unsubscribe method to match the right subscriber. + * + * @method contains + * @param {Function} fn the function to execute + * @param {Object} obj an object to be passed along when the event fires + * @return {boolean} true if the supplied arguments match this + * subscriber's signature. + */ +YAHOO.util.Subscriber.prototype.contains = function(fn, obj) { + if (obj) { + return (this.fn == fn && this.obj == obj); + } else { + return (this.fn == fn); + } +}; + +/** + * @method toString + */ +YAHOO.util.Subscriber.prototype.toString = function() { + return "Subscriber { obj: " + this.obj + + ", overrideContext: " + (this.overrideContext || "no") + " }"; +}; + +/** + * The Event Utility provides utilities for managing DOM Events and tools + * for building event systems + * + * @module event + * @title Event Utility + * @namespace YAHOO.util + * @requires yahoo + */ + +// The first instance of Event will win if it is loaded more than once. +// @TODO this needs to be changed so that only the state data that needs to +// be preserved is kept, while methods are overwritten/added as needed. +// This means that the module pattern can't be used. +if (!YAHOO.util.Event) { + +/** + * The event utility provides functions to add and remove event listeners, + * event cleansing. It also tries to automatically remove listeners it + * registers during the unload event. + * + * @class Event + * @static + */ + YAHOO.util.Event = function() { + + /** + * True after the onload event has fired + * @property loadComplete + * @type boolean + * @static + * @private + */ + var loadComplete = false, + + /** + * Cache of wrapped listeners + * @property listeners + * @type array + * @static + * @private + */ + listeners = [], + + + /** + * User-defined unload function that will be fired before all events + * are detached + * @property unloadListeners + * @type array + * @static + * @private + */ + unloadListeners = [], + + /** + * The number of times to poll after window.onload. This number is + * increased if additional late-bound handlers are requested after + * the page load. + * @property retryCount + * @static + * @private + */ + retryCount = 0, + + /** + * onAvailable listeners + * @property onAvailStack + * @static + * @private + */ + onAvailStack = [], + + /** + * Counter for auto id generation + * @property counter + * @static + * @private + */ + counter = 0, + + /** + * Normalized keycodes for webkit/safari + * @property webkitKeymap + * @type {int: int} + * @private + * @static + * @final + */ + webkitKeymap = { + 63232: 38, // up + 63233: 40, // down + 63234: 37, // left + 63235: 39, // right + 63276: 33, // page up + 63277: 34, // page down + 25: 9 // SHIFT-TAB (Safari provides a different key code in + // this case, even though the shiftKey modifier is set) + }, + + isIE = YAHOO.env.ua.ie, + + // String constants used by the addFocusListener and removeFocusListener methods + + FOCUSIN = "focusin", + FOCUSOUT = "focusout"; + + return { + + /** + * The number of times we should look for elements that are not + * in the DOM at the time the event is requested after the document + * has been loaded. The default is 500@amp;40 ms, so it will poll + * for 20 seconds or until all outstanding handlers are bound + * (whichever comes first). + * @property POLL_RETRYS + * @type int + * @static + * @final + */ + POLL_RETRYS: 500, + + /** + * The poll interval in milliseconds + * @property POLL_INTERVAL + * @type int + * @static + * @final + */ + POLL_INTERVAL: 40, + + /** + * Element to bind, int constant + * @property EL + * @type int + * @static + * @final + */ + EL: 0, + + /** + * Type of event, int constant + * @property TYPE + * @type int + * @static + * @final + */ + TYPE: 1, + + /** + * Function to execute, int constant + * @property FN + * @type int + * @static + * @final + */ + FN: 2, + + /** + * Function wrapped for context correction and cleanup, int constant + * @property WFN + * @type int + * @static + * @final + */ + WFN: 3, + + /** + * Object passed in by the user that will be returned as a + * parameter to the callback, int constant. Specific to + * unload listeners + * @property OBJ + * @type int + * @static + * @final + */ + UNLOAD_OBJ: 3, + + /** + * Adjusted context, either the element we are registering the event + * on or the custom object passed in by the listener, int constant + * @property ADJ_SCOPE + * @type int + * @static + * @final + */ + ADJ_SCOPE: 4, + + /** + * The original obj passed into addListener + * @property OBJ + * @type int + * @static + * @final + */ + OBJ: 5, + + /** + * The original context parameter passed into addListener + * @property OVERRIDE + * @type int + * @static + * @final + */ + OVERRIDE: 6, + + /** + * The original capture parameter passed into addListener + * @property CAPTURE + * @type int + * @static + * @final + */ + CAPTURE: 7, + + /** + * addListener/removeListener can throw errors in unexpected scenarios. + * These errors are suppressed, the method returns false, and this property + * is set + * @property lastError + * @static + * @type Error + */ + lastError: null, + + /** + * Safari detection + * @property isSafari + * @private + * @static + * @deprecated use YAHOO.env.ua.webkit + */ + isSafari: YAHOO.env.ua.webkit, + + /** + * webkit version + * @property webkit + * @type string + * @private + * @static + * @deprecated use YAHOO.env.ua.webkit + */ + webkit: YAHOO.env.ua.webkit, + + /** + * IE detection + * @property isIE + * @private + * @static + * @deprecated use YAHOO.env.ua.ie + */ + isIE: isIE, + + /** + * poll handle + * @property _interval + * @static + * @private + */ + _interval: null, + + /** + * document readystate poll handle + * @property _dri + * @static + * @private + */ + _dri: null, + + + /** + * Map of special event types + * @property _specialTypes + * @static + * @private + */ + _specialTypes: { + focusin: (isIE ? "focusin" : "focus"), + focusout: (isIE ? "focusout" : "blur") + }, + + + /** + * True when the document is initially usable + * @property DOMReady + * @type boolean + * @static + */ + DOMReady: false, + + /** + * Errors thrown by subscribers of custom events are caught + * and the error message is written to the debug console. If + * this property is set to true, it will also re-throw the + * error. + * @property throwErrors + * @type boolean + * @default false + */ + throwErrors: false, + + + /** + * @method startInterval + * @static + * @private + */ + startInterval: function() { + if (!this._interval) { + // var self = this; + // var callback = function() { self._tryPreloadAttach(); }; + // this._interval = setInterval(callback, this.POLL_INTERVAL); + this._interval = YAHOO.lang.later(this.POLL_INTERVAL, this, this._tryPreloadAttach, null, true); + } + }, + + /** + * Executes the supplied callback when the item with the supplied + * id is found. This is meant to be used to execute behavior as + * soon as possible as the page loads. If you use this after the + * initial page load it will poll for a fixed time for the element. + * The number of times it will poll and the frequency are + * configurable. By default it will poll for 10 seconds. + * + *

    The callback is executed with a single parameter: + * the custom object parameter, if provided.

    + * + * @method onAvailable + * + * @param {string||string[]} id the id of the element, or an array + * of ids to look for. + * @param {function} fn what to execute when the element is found. + * @param {object} obj an optional object to be passed back as + * a parameter to fn. + * @param {boolean|object} overrideContext If set to true, fn will execute + * in the context of obj, if set to an object it + * will execute in the context of that object + * @param checkContent {boolean} check child node readiness (onContentReady) + * @static + */ + onAvailable: function(id, fn, obj, overrideContext, checkContent) { + + var a = (YAHOO.lang.isString(id)) ? [id] : id; + + for (var i=0; iThe callback is executed with a single parameter: + * the custom object parameter, if provided.

    + * + * @method onContentReady + * + * @param {string} id the id of the element to look for. + * @param {function} fn what to execute when the element is ready. + * @param {object} obj an optional object to be passed back as + * a parameter to fn. + * @param {boolean|object} overrideContext If set to true, fn will execute + * in the context of obj. If an object, fn will + * exectute in the context of that object + * + * @static + */ + onContentReady: function(id, fn, obj, overrideContext) { + this.onAvailable(id, fn, obj, overrideContext, true); + }, + + /** + * Executes the supplied callback when the DOM is first usable. This + * will execute immediately if called after the DOMReady event has + * fired. @todo the DOMContentReady event does not fire when the + * script is dynamically injected into the page. This means the + * DOMReady custom event will never fire in FireFox or Opera when the + * library is injected. It _will_ fire in Safari, and the IE + * implementation would allow for us to fire it if the defered script + * is not available. We want this to behave the same in all browsers. + * Is there a way to identify when the script has been injected + * instead of included inline? Is there a way to know whether the + * window onload event has fired without having had a listener attached + * to it when it did so? + * + *

    The callback is a CustomEvent, so the signature is:

    + *

    type <string>, args <array>, customobject <object>

    + *

    For DOMReady events, there are no fire argments, so the + * signature is:

    + *

    "DOMReady", [], obj

    + * + * + * @method onDOMReady + * + * @param {function} fn what to execute when the element is found. + * @param {object} obj an optional object to be passed back as + * a parameter to fn. + * @param {boolean|object} overrideContext If set to true, fn will execute + * in the context of obj, if set to an object it + * will execute in the context of that object + * + * @static + */ + // onDOMReady: function(fn, obj, overrideContext) { + onDOMReady: function() { + this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent, arguments); + }, + + + /** + * Appends an event handler + * + * @method _addListener + * + * @param {String|HTMLElement|Array|NodeList} el An id, an element + * reference, or a collection of ids and/or elements to assign the + * listener to. + * @param {String} sType The type of event to append + * @param {Function} fn The method the event invokes + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the handler + * @param {Boolean|object} overrideContext If true, the obj passed in becomes + * the execution context of the listener. If an + * object, this object becomes the execution + * context. + * @param {boolen} capture capture or bubble phase + * @return {Boolean} True if the action was successful or defered, + * false if one or more of the elements + * could not have the listener attached, + * or if the operation throws an exception. + * @private + * @static + */ + _addListener: function(el, sType, fn, obj, overrideContext, bCapture) { + + if (!fn || !fn.call) { + YAHOO.log(sType + " addListener failed, invalid callback", "error", "Event"); + return false; + } + + // The el argument can be an array of elements or element ids. + if ( this._isValidCollection(el)) { + var ok = true; + for (var i=0,len=el.length; i-1; i--) { + ok = ( this.removeListener(el[i], sType, fn) && ok ); + } + return ok; + } + + if (!fn || !fn.call) { + // this.logger.debug("Error, function is not valid " + fn); + //return false; + return this.purgeElement(el, false, sType); + } + + if ("unload" == sType) { + + for (i=unloadListeners.length-1; i>-1; i--) { + li = unloadListeners[i]; + if (li && + li[0] == el && + li[1] == sType && + li[2] == fn) { + unloadListeners.splice(i, 1); + // unloadListeners[i]=null; + return true; + } + } + + return false; + } + + var cacheItem = null; + + // The index is a hidden parameter; needed to remove it from + // the method signature because it was tempting users to + // try and take advantage of it, which is not possible. + var index = arguments[3]; + + if ("undefined" === typeof index) { + index = this._getCacheIndex(listeners, el, sType, fn); + } + + if (index >= 0) { + cacheItem = listeners[index]; + } + + if (!el || !cacheItem) { + // this.logger.debug("cached listener not found"); + return false; + } + + // this.logger.debug("Removing handler: " + el + ", " + sType); + + var bCapture = cacheItem[this.CAPTURE] === true ? true : false; + + try { + this._simpleRemove(el, sType, cacheItem[this.WFN], bCapture); + } catch(ex) { + this.lastError = ex; + return false; + } + + // removed the wrapped handler + delete listeners[index][this.WFN]; + delete listeners[index][this.FN]; + listeners.splice(index, 1); + // listeners[index]=null; + + return true; + + }, + + /** + * Returns the event's target element. Safari sometimes provides + * a text node, and this is automatically resolved to the text + * node's parent so that it behaves like other browsers. + * @method getTarget + * @param {Event} ev the event + * @param {boolean} resolveTextNode when set to true the target's + * parent will be returned if the target is a + * text node. @deprecated, the text node is + * now resolved automatically + * @return {HTMLElement} the event's target + * @static + */ + getTarget: function(ev, resolveTextNode) { + var t = ev.target || ev.srcElement; + return this.resolveTextNode(t); + }, + + /** + * In some cases, some browsers will return a text node inside + * the actual element that was targeted. This normalizes the + * return value for getTarget and getRelatedTarget. + * + * If accessing a property of the node throws an error, this is + * probably the anonymous div wrapper Gecko adds inside text + * nodes. This likely will only occur when attempting to access + * the relatedTarget. In this case, we now return null because + * the anonymous div is completely useless and we do not know + * what the related target was because we can't even get to + * the element's parent node. + * + * @method resolveTextNode + * @param {HTMLElement} node node to resolve + * @return {HTMLElement} the normized node + * @static + */ + resolveTextNode: function(n) { + try { + if (n && 3 == n.nodeType) { + return n.parentNode; + } + } catch(e) { + return null; + } + + return n; + }, + + /** + * Returns the event's pageX + * @method getPageX + * @param {Event} ev the event + * @return {int} the event's pageX + * @static + */ + getPageX: function(ev) { + var x = ev.pageX; + if (!x && 0 !== x) { + x = ev.clientX || 0; + + if ( this.isIE ) { + x += this._getScrollLeft(); + } + } + + return x; + }, + + /** + * Returns the event's pageY + * @method getPageY + * @param {Event} ev the event + * @return {int} the event's pageY + * @static + */ + getPageY: function(ev) { + var y = ev.pageY; + if (!y && 0 !== y) { + y = ev.clientY || 0; + + if ( this.isIE ) { + y += this._getScrollTop(); + } + } + + + return y; + }, + + /** + * Returns the pageX and pageY properties as an indexed array. + * @method getXY + * @param {Event} ev the event + * @return {[x, y]} the pageX and pageY properties of the event + * @static + */ + getXY: function(ev) { + return [this.getPageX(ev), this.getPageY(ev)]; + }, + + /** + * Returns the event's related target + * @method getRelatedTarget + * @param {Event} ev the event + * @return {HTMLElement} the event's relatedTarget + * @static + */ + getRelatedTarget: function(ev) { + var t = ev.relatedTarget; + if (!t) { + if (ev.type == "mouseout") { + t = ev.toElement; + } else if (ev.type == "mouseover") { + t = ev.fromElement; + } + } + + return this.resolveTextNode(t); + }, + + /** + * Returns the time of the event. If the time is not included, the + * event is modified using the current time. + * @method getTime + * @param {Event} ev the event + * @return {Date} the time of the event + * @static + */ + getTime: function(ev) { + if (!ev.time) { + var t = new Date().getTime(); + try { + ev.time = t; + } catch(ex) { + this.lastError = ex; + return t; + } + } + + return ev.time; + }, + + /** + * Convenience method for stopPropagation + preventDefault + * @method stopEvent + * @param {Event} ev the event + * @static + */ + stopEvent: function(ev) { + this.stopPropagation(ev); + this.preventDefault(ev); + }, + + /** + * Stops event propagation + * @method stopPropagation + * @param {Event} ev the event + * @static + */ + stopPropagation: function(ev) { + if (ev.stopPropagation) { + ev.stopPropagation(); + } else { + ev.cancelBubble = true; + } + }, + + /** + * Prevents the default behavior of the event + * @method preventDefault + * @param {Event} ev the event + * @static + */ + preventDefault: function(ev) { + if (ev.preventDefault) { + ev.preventDefault(); + } else { + ev.returnValue = false; + } + }, + + /** + * Finds the event in the window object, the caller's arguments, or + * in the arguments of another method in the callstack. This is + * executed automatically for events registered through the event + * manager, so the implementer should not normally need to execute + * this function at all. + * @method getEvent + * @param {Event} e the event parameter from the handler + * @param {HTMLElement} boundEl the element the listener is attached to + * @return {Event} the event + * @static + */ + getEvent: function(e, boundEl) { + var ev = e || window.event; + + if (!ev) { + var c = this.getEvent.caller; + while (c) { + ev = c.arguments[0]; + if (ev && Event == ev.constructor) { + break; + } + c = c.caller; + } + } + + return ev; + }, + + /** + * Returns the charcode for an event + * @method getCharCode + * @param {Event} ev the event + * @return {int} the event's charCode + * @static + */ + getCharCode: function(ev) { + var code = ev.keyCode || ev.charCode || 0; + + // webkit key normalization + if (YAHOO.env.ua.webkit && (code in webkitKeymap)) { + code = webkitKeymap[code]; + } + return code; + }, + + /** + * Locating the saved event handler data by function ref + * + * @method _getCacheIndex + * @static + * @private + */ + _getCacheIndex: function(a, el, sType, fn) { + for (var i=0, l=a.length; i 0 && onAvailStack.length > 0); + } + + // onAvailable + var notAvail = []; + + var executeItem = function (el, item) { + var context = el; + if (item.overrideContext) { + if (item.overrideContext === true) { + context = item.obj; + } else { + context = item.overrideContext; + } + } + item.fn.call(context, item.obj); + }; + + var i, len, item, el, ready=[]; + + // onAvailable onContentReady + for (i=0, len=onAvailStack.length; i-1; i--) { + item = onAvailStack[i]; + if (!item || !item.id) { + onAvailStack.splice(i, 1); + } + } + + this.startInterval(); + } else { + if (this._interval) { + // clearInterval(this._interval); + this._interval.cancel(); + this._interval = null; + } + } + + this.locked = false; + + }, + + /** + * Removes all listeners attached to the given element via addListener. + * Optionally, the node's children can also be purged. + * Optionally, you can specify a specific type of event to remove. + * @method purgeElement + * @param {HTMLElement} el the element to purge + * @param {boolean} recurse recursively purge this element's children + * as well. Use with caution. + * @param {string} sType optional type of listener to purge. If + * left out, all listeners will be removed + * @static + */ + purgeElement: function(el, recurse, sType) { + var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el; + var elListeners = this.getListeners(oEl, sType), i, len; + if (elListeners) { + for (i=elListeners.length-1; i>-1; i--) { + var l = elListeners[i]; + this.removeListener(oEl, l.type, l.fn); + } + } + + if (recurse && oEl && oEl.childNodes) { + for (i=0,len=oEl.childNodes.length; i-1; j--) { + l = listeners[j]; + if (l) { + try { + EU.removeListener(l[EU.EL], l[EU.TYPE], l[EU.FN], j); + } catch(e2) {} + } + } + l=null; + } + + try { + EU._simpleRemove(window, "unload", EU._unload); + EU._simpleRemove(window, "load", EU._load); + } catch(e3) {} + + }, + + /** + * Returns scrollLeft + * @method _getScrollLeft + * @static + * @private + */ + _getScrollLeft: function() { + return this._getScroll()[1]; + }, + + /** + * Returns scrollTop + * @method _getScrollTop + * @static + * @private + */ + _getScrollTop: function() { + return this._getScroll()[0]; + }, + + /** + * Returns the scrollTop and scrollLeft. Used to calculate the + * pageX and pageY in Internet Explorer + * @method _getScroll + * @static + * @private + */ + _getScroll: function() { + var dd = document.documentElement, db = document.body; + if (dd && (dd.scrollTop || dd.scrollLeft)) { + return [dd.scrollTop, dd.scrollLeft]; + } else if (db) { + return [db.scrollTop, db.scrollLeft]; + } else { + return [0, 0]; + } + }, + + /** + * Used by old versions of CustomEvent, restored for backwards + * compatibility + * @method regCE + * @private + * @static + * @deprecated still here for backwards compatibility + */ + regCE: function() {}, + + /** + * Adds a DOM event directly without the caching, cleanup, context adj, etc + * + * @method _simpleAdd + * @param {HTMLElement} el the element to bind the handler to + * @param {string} sType the type of event handler + * @param {function} fn the callback to invoke + * @param {boolen} capture capture or bubble phase + * @static + * @private + */ + _simpleAdd: function () { + if (window.addEventListener) { + return function(el, sType, fn, capture) { + el.addEventListener(sType, fn, (capture)); + }; + } else if (window.attachEvent) { + return function(el, sType, fn, capture) { + el.attachEvent("on" + sType, fn); + }; + } else { + return function(){}; + } + }(), + + /** + * Basic remove listener + * + * @method _simpleRemove + * @param {HTMLElement} el the element to bind the handler to + * @param {string} sType the type of event handler + * @param {function} fn the callback to invoke + * @param {boolen} capture capture or bubble phase + * @static + * @private + */ + _simpleRemove: function() { + if (window.removeEventListener) { + return function (el, sType, fn, capture) { + el.removeEventListener(sType, fn, (capture)); + }; + } else if (window.detachEvent) { + return function (el, sType, fn) { + el.detachEvent("on" + sType, fn); + }; + } else { + return function(){}; + } + }() + }; + + }(); + + (function() { + var EU = YAHOO.util.Event; + + /** + * Appends an event handler. This is an alias for addListener + * + * @method on + * + * @param {String|HTMLElement|Array|NodeList} el An id, an element + * reference, or a collection of ids and/or elements to assign the + * listener to. + * @param {String} sType The type of event to append + * @param {Function} fn The method the event invokes + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the handler + * @param {Boolean|object} overrideContext If true, the obj passed in becomes + * the execution context of the listener. If an + * object, this object becomes the execution + * context. + * @return {Boolean} True if the action was successful or defered, + * false if one or more of the elements + * could not have the listener attached, + * or if the operation throws an exception. + * @static + */ + EU.on = EU.addListener; + + /** + * YAHOO.util.Event.onFocus is an alias for addFocusListener + * @method onFocus + * @see addFocusListener + * @static + * @deprecated use YAHOO.util.Event.on and specify "focusin" as the event type. + */ + EU.onFocus = EU.addFocusListener; + + /** + * YAHOO.util.Event.onBlur is an alias for addBlurListener + * @method onBlur + * @see addBlurListener + * @static + * @deprecated use YAHOO.util.Event.on and specify "focusout" as the event type. + */ + EU.onBlur = EU.addBlurListener; + +/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ + + // Internet Explorer: use the readyState of a defered script. + // This isolates what appears to be a safe moment to manipulate + // the DOM prior to when the document's readyState suggests + // it is safe to do so. + if (EU.isIE) { + if (self !== self.top) { + document.onreadystatechange = function() { + if (document.readyState == 'complete') { + document.onreadystatechange = null; + EU._ready(); + } + }; + } else { + + // Process onAvailable/onContentReady items when the + // DOM is ready. + YAHOO.util.Event.onDOMReady( + YAHOO.util.Event._tryPreloadAttach, + YAHOO.util.Event, true); + + var n = document.createElement('p'); + + EU._dri = setInterval(function() { + try { + // throws an error if doc is not ready + n.doScroll('left'); + clearInterval(EU._dri); + EU._dri = null; + EU._ready(); + n = null; + } catch (ex) { + } + }, EU.POLL_INTERVAL); + } + + // The document's readyState in Safari currently will + // change to loaded/complete before images are loaded. + } else if (EU.webkit && EU.webkit < 525) { + + EU._dri = setInterval(function() { + var rs=document.readyState; + if ("loaded" == rs || "complete" == rs) { + clearInterval(EU._dri); + EU._dri = null; + EU._ready(); + } + }, EU.POLL_INTERVAL); + + // FireFox and Opera: These browsers provide a event for this + // moment. The latest WebKit releases now support this event. + } else { + + EU._simpleAdd(document, "DOMContentLoaded", EU._ready); + + } + ///////////////////////////////////////////////////////////// + + + EU._simpleAdd(window, "load", EU._load); + EU._simpleAdd(window, "unload", EU._unload); + EU._tryPreloadAttach(); + })(); + +} +/** + * EventProvider is designed to be used with YAHOO.augment to wrap + * CustomEvents in an interface that allows events to be subscribed to + * and fired by name. This makes it possible for implementing code to + * subscribe to an event that either has not been created yet, or will + * not be created at all. + * + * @Class EventProvider + */ +YAHOO.util.EventProvider = function() { }; + +YAHOO.util.EventProvider.prototype = { + + /** + * Private storage of custom events + * @property __yui_events + * @type Object[] + * @private + */ + __yui_events: null, + + /** + * Private storage of custom event subscribers + * @property __yui_subscribers + * @type Object[] + * @private + */ + __yui_subscribers: null, + + /** + * Subscribe to a CustomEvent by event type + * + * @method subscribe + * @param p_type {string} the type, or name of the event + * @param p_fn {function} the function to exectute when the event fires + * @param p_obj {Object} An object to be passed along when the event + * fires + * @param overrideContext {boolean} If true, the obj passed in becomes the + * execution scope of the listener + */ + subscribe: function(p_type, p_fn, p_obj, overrideContext) { + + this.__yui_events = this.__yui_events || {}; + var ce = this.__yui_events[p_type]; + + if (ce) { + ce.subscribe(p_fn, p_obj, overrideContext); + } else { + this.__yui_subscribers = this.__yui_subscribers || {}; + var subs = this.__yui_subscribers; + if (!subs[p_type]) { + subs[p_type] = []; + } + subs[p_type].push( + { fn: p_fn, obj: p_obj, overrideContext: overrideContext } ); + } + }, + + /** + * Unsubscribes one or more listeners the from the specified event + * @method unsubscribe + * @param p_type {string} The type, or name of the event. If the type + * is not specified, it will attempt to remove + * the listener from all hosted events. + * @param p_fn {Function} The subscribed function to unsubscribe, if not + * supplied, all subscribers will be removed. + * @param p_obj {Object} The custom object passed to subscribe. This is + * optional, but if supplied will be used to + * disambiguate multiple listeners that are the same + * (e.g., you subscribe many object using a function + * that lives on the prototype) + * @return {boolean} true if the subscriber was found and detached. + */ + unsubscribe: function(p_type, p_fn, p_obj) { + this.__yui_events = this.__yui_events || {}; + var evts = this.__yui_events; + if (p_type) { + var ce = evts[p_type]; + if (ce) { + return ce.unsubscribe(p_fn, p_obj); + } + } else { + var ret = true; + for (var i in evts) { + if (YAHOO.lang.hasOwnProperty(evts, i)) { + ret = ret && evts[i].unsubscribe(p_fn, p_obj); + } + } + return ret; + } + + return false; + }, + + /** + * Removes all listeners from the specified event. If the event type + * is not specified, all listeners from all hosted custom events will + * be removed. + * @method unsubscribeAll + * @param p_type {string} The type, or name of the event + */ + unsubscribeAll: function(p_type) { + return this.unsubscribe(p_type); + }, + + /** + * Creates a new custom event of the specified type. If a custom event + * by that name already exists, it will not be re-created. In either + * case the custom event is returned. + * + * @method createEvent + * + * @param p_type {string} the type, or name of the event + * @param p_config {object} optional config params. Valid properties are: + * + *
      + *
    • + * scope: defines the default execution scope. If not defined + * the default scope will be this instance. + *
    • + *
    • + * silent: if true, the custom event will not generate log messages. + * This is false by default. + *
    • + *
    • + * fireOnce: if true, the custom event will only notify subscribers + * once regardless of the number of times the event is fired. In + * addition, new subscribers will be executed immediately if the + * event has already fired. + * This is false by default. + *
    • + *
    • + * onSubscribeCallback: specifies a callback to execute when the + * event has a new subscriber. This will fire immediately for + * each queued subscriber if any exist prior to the creation of + * the event. + *
    • + *
    + * + * @return {CustomEvent} the custom event + * + */ + createEvent: function(p_type, p_config) { + + this.__yui_events = this.__yui_events || {}; + var opts = p_config || {}, + events = this.__yui_events, ce; + + if (events[p_type]) { +YAHOO.log("EventProvider createEvent skipped: '"+p_type+"' already exists"); + } else { + + ce = new YAHOO.util.CustomEvent(p_type, opts.scope || this, opts.silent, + YAHOO.util.CustomEvent.FLAT, opts.fireOnce); + + events[p_type] = ce; + + if (opts.onSubscribeCallback) { + ce.subscribeEvent.subscribe(opts.onSubscribeCallback); + } + + this.__yui_subscribers = this.__yui_subscribers || {}; + var qs = this.__yui_subscribers[p_type]; + + if (qs) { + for (var i=0; i + *
  • The first argument fire() was executed with
  • + *
  • The custom object (if any) that was passed into the subscribe() + * method
  • + * + * @method fireEvent + * @param p_type {string} the type, or name of the event + * @param arguments {Object*} an arbitrary set of parameters to pass to + * the handler. + * @return {boolean} the return value from CustomEvent.fire + * + */ + fireEvent: function(p_type) { + + this.__yui_events = this.__yui_events || {}; + var ce = this.__yui_events[p_type]; + + if (!ce) { +YAHOO.log(p_type + "event fired before it was created."); + return null; + } + + var args = []; + for (var i=1; i0){i=c[0];}try{b=g.fn.call(f,i,g.obj);}catch(h){this.lastError=h;if(a){throw h;}}}else{try{b=g.fn.call(f,this.type,c,g.obj);}catch(d){this.lastError=d;if(a){throw d;}}}return b;},unsubscribeAll:function(){var a=this.subscribers.length,b;for(b=a-1;b>-1;b--){this._delete(b);}this.subscribers=[];return a;},_delete:function(a){var b=this.subscribers[a];if(b){delete b.fn;delete b.obj;}this.subscribers.splice(a,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(a,b,c){this.fn=a;this.obj=YAHOO.lang.isUndefined(b)?null:b;this.overrideContext=c;};YAHOO.util.Subscriber.prototype.getScope=function(a){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return a;};YAHOO.util.Subscriber.prototype.contains=function(a,b){if(b){return(this.fn==a&&this.obj==b);}else{return(this.fn==a);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var g=false,h=[],j=[],a=0,e=[],b=0,c={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},d=YAHOO.env.ua.ie,f="focusin",i="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:d,_interval:null,_dri:null,_specialTypes:{focusin:(d?"focusin":"focus"),focusout:(d?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(q,m,o,p,n){var k=(YAHOO.lang.isString(q))?[q]:q;for(var l=0;l-1;m--){s=(this.removeListener(l[m],k,r)&&s);}return s;}}if(!r||!r.call){return this.purgeElement(l,false,k);}if("unload"==k){for(m=j.length-1;m>-1;m--){u=j[m];if(u&&u[0]==l&&u[1]==k&&u[2]==r){j.splice(m,1);return true;}}return false;}var n=null;var o=arguments[3];if("undefined"===typeof o){o=this._getCacheIndex(h,l,k,r);}if(o>=0){n=h[o];}if(!l||!n){return false;}var t=n[this.CAPTURE]===true?true:false;try{this._simpleRemove(l,k,n[this.WFN],t);}catch(q){this.lastError=q;return false;}delete h[o][this.WFN];delete h[o][this.FN];h.splice(o,1);return true;},getTarget:function(m,l){var k=m.target||m.srcElement;return this.resolveTextNode(k);},resolveTextNode:function(l){try{if(l&&3==l.nodeType){return l.parentNode;}}catch(k){return null;}return l;},getPageX:function(l){var k=l.pageX;if(!k&&0!==k){k=l.clientX||0;if(this.isIE){k+=this._getScrollLeft();}}return k;},getPageY:function(k){var l=k.pageY;if(!l&&0!==l){l=k.clientY||0;if(this.isIE){l+=this._getScrollTop();}}return l;},getXY:function(k){return[this.getPageX(k),this.getPageY(k)];},getRelatedTarget:function(l){var k=l.relatedTarget; +if(!k){if(l.type=="mouseout"){k=l.toElement;}else{if(l.type=="mouseover"){k=l.fromElement;}}}return this.resolveTextNode(k);},getTime:function(m){if(!m.time){var l=new Date().getTime();try{m.time=l;}catch(k){this.lastError=k;return l;}}return m.time;},stopEvent:function(k){this.stopPropagation(k);this.preventDefault(k);},stopPropagation:function(k){if(k.stopPropagation){k.stopPropagation();}else{k.cancelBubble=true;}},preventDefault:function(k){if(k.preventDefault){k.preventDefault();}else{k.returnValue=false;}},getEvent:function(m,k){var l=m||window.event;if(!l){var n=this.getEvent.caller;while(n){l=n.arguments[0];if(l&&Event==l.constructor){break;}n=n.caller;}}return l;},getCharCode:function(l){var k=l.keyCode||l.charCode||0;if(YAHOO.env.ua.webkit&&(k in c)){k=c[k];}return k;},_getCacheIndex:function(n,q,r,p){for(var o=0,m=n.length;o0&&e.length>0);}var p=[];var r=function(t,u){var s=t;if(u.overrideContext){if(u.overrideContext===true){s=u.obj;}else{s=u.overrideContext;}}u.fn.call(s,u.obj);};var l,k,o,n,m=[];for(l=0,k=e.length;l-1;l--){o=e[l];if(!o||!o.id){e.splice(l,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(p,q,s){var n=(YAHOO.lang.isString(p))?this.getEl(p):p;var r=this.getListeners(n,s),o,k;if(r){for(o=r.length-1;o>-1;o--){var m=r[o];this.removeListener(n,m.type,m.fn);}}if(q&&n&&n.childNodes){for(o=0,k=n.childNodes.length;o-1;o--){n=h[o];if(n){try{m.removeListener(n[m.EL],n[m.TYPE],n[m.FN],o);}catch(v){}}}n=null;}try{m._simpleRemove(window,"unload",m._unload);m._simpleRemove(window,"load",m._load);}catch(u){}},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var k=document.documentElement,l=document.body;if(k&&(k.scrollTop||k.scrollLeft)){return[k.scrollTop,k.scrollLeft];}else{if(l){return[l.scrollTop,l.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(m,n,l,k){m.addEventListener(n,l,(k));};}else{if(window.attachEvent){return function(m,n,l,k){m.attachEvent("on"+n,l);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(m,n,l,k){m.removeEventListener(n,l,(k));};}else{if(window.detachEvent){return function(l,m,k){l.detachEvent("on"+m,k);};}else{return function(){};}}}()};}();(function(){var a=YAHOO.util.Event;a.on=a.addListener;a.onFocus=a.addFocusListener;a.onBlur=a.addBlurListener; +/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ +if(a.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;a._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var b=document.createElement("p");a._dri=setInterval(function(){try{b.doScroll("left");clearInterval(a._dri);a._dri=null;a._ready();b=null;}catch(c){}},a.POLL_INTERVAL);}}else{if(a.webkit&&a.webkit<525){a._dri=setInterval(function(){var c=document.readyState;if("loaded"==c||"complete"==c){clearInterval(a._dri);a._dri=null;a._ready();}},a.POLL_INTERVAL);}else{a._simpleAdd(document,"DOMContentLoaded",a._ready);}}a._simpleAdd(window,"load",a._load);a._simpleAdd(window,"unload",a._unload);a._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(a,c,f,e){this.__yui_events=this.__yui_events||{};var d=this.__yui_events[a];if(d){d.subscribe(c,f,e);}else{this.__yui_subscribers=this.__yui_subscribers||{};var b=this.__yui_subscribers;if(!b[a]){b[a]=[];}b[a].push({fn:c,obj:f,overrideContext:e});}},unsubscribe:function(c,e,g){this.__yui_events=this.__yui_events||{};var a=this.__yui_events;if(c){var f=a[c];if(f){return f.unsubscribe(e,g);}}else{var b=true;for(var d in a){if(YAHOO.lang.hasOwnProperty(a,d)){b=b&&a[d].unsubscribe(e,g); +}}return b;}return false;},unsubscribeAll:function(a){return this.unsubscribe(a);},createEvent:function(b,g){this.__yui_events=this.__yui_events||{};var e=g||{},d=this.__yui_events,f;if(d[b]){}else{f=new YAHOO.util.CustomEvent(b,e.scope||this,e.silent,YAHOO.util.CustomEvent.FLAT,e.fireOnce);d[b]=f;if(e.onSubscribeCallback){f.subscribeEvent.subscribe(e.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var a=this.__yui_subscribers[b];if(a){for(var c=0;c + *
  • YAHOO.util.CustomEvent.LIST: + *
      + *
    • param1: event name
    • + *
    • param2: array of arguments sent to fire
    • + *
    • param3: a custom object supplied by the subscriber
    • + *
    + *
  • + *
  • YAHOO.util.CustomEvent.FLAT + *
      + *
    • param1: the first argument passed to fire. If you need to + * pass multiple parameters, use and array or object literal
    • + *
    • param2: a custom object supplied by the subscriber
    • + *
    + *
  • + * + * @property signature + * @type int + */ + this.signature = signature || YAHOO.util.CustomEvent.LIST; + + /** + * The subscribers to this event + * @property subscribers + * @type Subscriber[] + */ + this.subscribers = []; + + if (!this.silent) { + } + + var onsubscribeType = "_YUICEOnSubscribe"; + + // Only add subscribe events for events that are not generated by + // CustomEvent + if (type !== onsubscribeType) { + + /** + * Custom events provide a custom event that fires whenever there is + * a new subscriber to the event. This provides an opportunity to + * handle the case where there is a non-repeating event that has + * already fired has a new subscriber. + * + * @event subscribeEvent + * @type YAHOO.util.CustomEvent + * @param fn {Function} The function to execute + * @param obj An object to be passed along when the event fires. + * Defaults to the custom event. + * @param override If true, the obj passed in becomes the + * execution context of the listener. If an object, that object becomes + * the execution context. Defaults to the custom event. + */ + this.subscribeEvent = + new YAHOO.util.CustomEvent(onsubscribeType, this, true); + + } + + + /** + * In order to make it possible to execute the rest of the subscriber + * stack when one thows an exception, the subscribers exceptions are + * caught. The most recent exception is stored in this property + * @property lastError + * @type Error + */ + this.lastError = null; +}; + +/** + * Subscriber listener sigature constant. The LIST type returns three + * parameters: the event type, the array of args passed to fire, and + * the optional custom object + * @property YAHOO.util.CustomEvent.LIST + * @static + * @type int + */ +YAHOO.util.CustomEvent.LIST = 0; + +/** + * Subscriber listener sigature constant. The FLAT type returns two + * parameters: the first argument passed to fire and the optional + * custom object + * @property YAHOO.util.CustomEvent.FLAT + * @static + * @type int + */ +YAHOO.util.CustomEvent.FLAT = 1; + +YAHOO.util.CustomEvent.prototype = { + + /** + * Subscribes the caller to this event + * @method subscribe + * @param {Function} fn The function to execute + * @param {Object} obj An object to be passed along when the event + * fires. + * @param {boolean|Object} overrideContext If true, the obj passed in + * becomes the execution. + * context of the listener. If an object, that object becomes the execution + * context. + */ + subscribe: function(fn, obj, overrideContext) { + + if (!fn) { +throw new Error("Invalid callback for subscriber to '" + this.type + "'"); + } + + if (this.subscribeEvent) { + this.subscribeEvent.fire(fn, obj, overrideContext); + } + + var s = new YAHOO.util.Subscriber(fn, obj, overrideContext); + + if (this.fireOnce && this.fired) { + this.notify(s, this.firedWith); + } else { + this.subscribers.push(s); + } + }, + + /** + * Unsubscribes subscribers. + * @method unsubscribe + * @param {Function} fn The subscribed function to remove, if not supplied + * all will be removed + * @param {Object} obj The custom object passed to subscribe. This is + * optional, but if supplied will be used to + * disambiguate multiple listeners that are the same + * (e.g., you subscribe many object using a function + * that lives on the prototype) + * @return {boolean} True if the subscriber was found and detached. + */ + unsubscribe: function(fn, obj) { + + if (!fn) { + return this.unsubscribeAll(); + } + + var found = false; + for (var i=0, len=this.subscribers.length; i + *
  • The type of event
  • + *
  • All of the arguments fire() was executed with as an array
  • + *
  • The custom object (if any) that was passed into the subscribe() + * method
  • + * + * @method fire + * @param {Object*} arguments an arbitrary set of parameters to pass to + * the handler. + * @return {boolean} false if one of the subscribers returned false, + * true otherwise + */ + fire: function() { + + this.lastError = null; + + var errors = [], + len=this.subscribers.length; + + + var args=[].slice.call(arguments, 0), ret=true, i, rebuild=false; + + if (this.fireOnce) { + if (this.fired) { + return true; + } else { + this.firedWith = args; + } + } + + this.fired = true; + + if (!len && this.silent) { + return true; + } + + if (!this.silent) { + } + + // make a copy of the subscribers so that there are + // no index problems if one subscriber removes another. + var subs = this.subscribers.slice(); + + for (i=0; i 0) { + param = args[0]; + } + + try { + ret = s.fn.call(scope, param, s.obj); + } catch(e) { + this.lastError = e; + // errors.push(e); + if (throwErrors) { + throw e; + } + } + } else { + try { + ret = s.fn.call(scope, this.type, args, s.obj); + } catch(ex) { + this.lastError = ex; + if (throwErrors) { + throw ex; + } + } + } + + return ret; + }, + + /** + * Removes all listeners + * @method unsubscribeAll + * @return {int} The number of listeners unsubscribed + */ + unsubscribeAll: function() { + var l = this.subscribers.length, i; + for (i=l-1; i>-1; i--) { + this._delete(i); + } + + this.subscribers=[]; + + return l; + }, + + /** + * @method _delete + * @private + */ + _delete: function(index) { + var s = this.subscribers[index]; + if (s) { + delete s.fn; + delete s.obj; + } + + // this.subscribers[index]=null; + this.subscribers.splice(index, 1); + }, + + /** + * @method toString + */ + toString: function() { + return "CustomEvent: " + "'" + this.type + "', " + + "context: " + this.scope; + + } +}; + +///////////////////////////////////////////////////////////////////// + +/** + * Stores the subscriber information to be used when the event fires. + * @param {Function} fn The function to execute + * @param {Object} obj An object to be passed along when the event fires + * @param {boolean} overrideContext If true, the obj passed in becomes the execution + * context of the listener + * @class Subscriber + * @constructor + */ +YAHOO.util.Subscriber = function(fn, obj, overrideContext) { + + /** + * The callback that will be execute when the event fires + * @property fn + * @type function + */ + this.fn = fn; + + /** + * An optional custom object that will passed to the callback when + * the event fires + * @property obj + * @type object + */ + this.obj = YAHOO.lang.isUndefined(obj) ? null : obj; + + /** + * The default execution context for the event listener is defined when the + * event is created (usually the object which contains the event). + * By setting overrideContext to true, the execution context becomes the custom + * object passed in by the subscriber. If overrideContext is an object, that + * object becomes the context. + * @property overrideContext + * @type boolean|object + */ + this.overrideContext = overrideContext; + +}; + +/** + * Returns the execution context for this listener. If overrideContext was set to true + * the custom obj will be the context. If overrideContext is an object, that is the + * context, otherwise the default context will be used. + * @method getScope + * @param {Object} defaultScope the context to use if this listener does not + * override it. + */ +YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) { + if (this.overrideContext) { + if (this.overrideContext === true) { + return this.obj; + } else { + return this.overrideContext; + } + } + return defaultScope; +}; + +/** + * Returns true if the fn and obj match this objects properties. + * Used by the unsubscribe method to match the right subscriber. + * + * @method contains + * @param {Function} fn the function to execute + * @param {Object} obj an object to be passed along when the event fires + * @return {boolean} true if the supplied arguments match this + * subscriber's signature. + */ +YAHOO.util.Subscriber.prototype.contains = function(fn, obj) { + if (obj) { + return (this.fn == fn && this.obj == obj); + } else { + return (this.fn == fn); + } +}; + +/** + * @method toString + */ +YAHOO.util.Subscriber.prototype.toString = function() { + return "Subscriber { obj: " + this.obj + + ", overrideContext: " + (this.overrideContext || "no") + " }"; +}; + +/** + * The Event Utility provides utilities for managing DOM Events and tools + * for building event systems + * + * @module event + * @title Event Utility + * @namespace YAHOO.util + * @requires yahoo + */ + +// The first instance of Event will win if it is loaded more than once. +// @TODO this needs to be changed so that only the state data that needs to +// be preserved is kept, while methods are overwritten/added as needed. +// This means that the module pattern can't be used. +if (!YAHOO.util.Event) { + +/** + * The event utility provides functions to add and remove event listeners, + * event cleansing. It also tries to automatically remove listeners it + * registers during the unload event. + * + * @class Event + * @static + */ + YAHOO.util.Event = function() { + + /** + * True after the onload event has fired + * @property loadComplete + * @type boolean + * @static + * @private + */ + var loadComplete = false, + + /** + * Cache of wrapped listeners + * @property listeners + * @type array + * @static + * @private + */ + listeners = [], + + + /** + * User-defined unload function that will be fired before all events + * are detached + * @property unloadListeners + * @type array + * @static + * @private + */ + unloadListeners = [], + + /** + * The number of times to poll after window.onload. This number is + * increased if additional late-bound handlers are requested after + * the page load. + * @property retryCount + * @static + * @private + */ + retryCount = 0, + + /** + * onAvailable listeners + * @property onAvailStack + * @static + * @private + */ + onAvailStack = [], + + /** + * Counter for auto id generation + * @property counter + * @static + * @private + */ + counter = 0, + + /** + * Normalized keycodes for webkit/safari + * @property webkitKeymap + * @type {int: int} + * @private + * @static + * @final + */ + webkitKeymap = { + 63232: 38, // up + 63233: 40, // down + 63234: 37, // left + 63235: 39, // right + 63276: 33, // page up + 63277: 34, // page down + 25: 9 // SHIFT-TAB (Safari provides a different key code in + // this case, even though the shiftKey modifier is set) + }, + + isIE = YAHOO.env.ua.ie, + + // String constants used by the addFocusListener and removeFocusListener methods + + FOCUSIN = "focusin", + FOCUSOUT = "focusout"; + + return { + + /** + * The number of times we should look for elements that are not + * in the DOM at the time the event is requested after the document + * has been loaded. The default is 500@amp;40 ms, so it will poll + * for 20 seconds or until all outstanding handlers are bound + * (whichever comes first). + * @property POLL_RETRYS + * @type int + * @static + * @final + */ + POLL_RETRYS: 500, + + /** + * The poll interval in milliseconds + * @property POLL_INTERVAL + * @type int + * @static + * @final + */ + POLL_INTERVAL: 40, + + /** + * Element to bind, int constant + * @property EL + * @type int + * @static + * @final + */ + EL: 0, + + /** + * Type of event, int constant + * @property TYPE + * @type int + * @static + * @final + */ + TYPE: 1, + + /** + * Function to execute, int constant + * @property FN + * @type int + * @static + * @final + */ + FN: 2, + + /** + * Function wrapped for context correction and cleanup, int constant + * @property WFN + * @type int + * @static + * @final + */ + WFN: 3, + + /** + * Object passed in by the user that will be returned as a + * parameter to the callback, int constant. Specific to + * unload listeners + * @property OBJ + * @type int + * @static + * @final + */ + UNLOAD_OBJ: 3, + + /** + * Adjusted context, either the element we are registering the event + * on or the custom object passed in by the listener, int constant + * @property ADJ_SCOPE + * @type int + * @static + * @final + */ + ADJ_SCOPE: 4, + + /** + * The original obj passed into addListener + * @property OBJ + * @type int + * @static + * @final + */ + OBJ: 5, + + /** + * The original context parameter passed into addListener + * @property OVERRIDE + * @type int + * @static + * @final + */ + OVERRIDE: 6, + + /** + * The original capture parameter passed into addListener + * @property CAPTURE + * @type int + * @static + * @final + */ + CAPTURE: 7, + + /** + * addListener/removeListener can throw errors in unexpected scenarios. + * These errors are suppressed, the method returns false, and this property + * is set + * @property lastError + * @static + * @type Error + */ + lastError: null, + + /** + * Safari detection + * @property isSafari + * @private + * @static + * @deprecated use YAHOO.env.ua.webkit + */ + isSafari: YAHOO.env.ua.webkit, + + /** + * webkit version + * @property webkit + * @type string + * @private + * @static + * @deprecated use YAHOO.env.ua.webkit + */ + webkit: YAHOO.env.ua.webkit, + + /** + * IE detection + * @property isIE + * @private + * @static + * @deprecated use YAHOO.env.ua.ie + */ + isIE: isIE, + + /** + * poll handle + * @property _interval + * @static + * @private + */ + _interval: null, + + /** + * document readystate poll handle + * @property _dri + * @static + * @private + */ + _dri: null, + + + /** + * Map of special event types + * @property _specialTypes + * @static + * @private + */ + _specialTypes: { + focusin: (isIE ? "focusin" : "focus"), + focusout: (isIE ? "focusout" : "blur") + }, + + + /** + * True when the document is initially usable + * @property DOMReady + * @type boolean + * @static + */ + DOMReady: false, + + /** + * Errors thrown by subscribers of custom events are caught + * and the error message is written to the debug console. If + * this property is set to true, it will also re-throw the + * error. + * @property throwErrors + * @type boolean + * @default false + */ + throwErrors: false, + + + /** + * @method startInterval + * @static + * @private + */ + startInterval: function() { + if (!this._interval) { + // var self = this; + // var callback = function() { self._tryPreloadAttach(); }; + // this._interval = setInterval(callback, this.POLL_INTERVAL); + this._interval = YAHOO.lang.later(this.POLL_INTERVAL, this, this._tryPreloadAttach, null, true); + } + }, + + /** + * Executes the supplied callback when the item with the supplied + * id is found. This is meant to be used to execute behavior as + * soon as possible as the page loads. If you use this after the + * initial page load it will poll for a fixed time for the element. + * The number of times it will poll and the frequency are + * configurable. By default it will poll for 10 seconds. + * + *

    The callback is executed with a single parameter: + * the custom object parameter, if provided.

    + * + * @method onAvailable + * + * @param {string||string[]} id the id of the element, or an array + * of ids to look for. + * @param {function} fn what to execute when the element is found. + * @param {object} obj an optional object to be passed back as + * a parameter to fn. + * @param {boolean|object} overrideContext If set to true, fn will execute + * in the context of obj, if set to an object it + * will execute in the context of that object + * @param checkContent {boolean} check child node readiness (onContentReady) + * @static + */ + onAvailable: function(id, fn, obj, overrideContext, checkContent) { + + var a = (YAHOO.lang.isString(id)) ? [id] : id; + + for (var i=0; iThe callback is executed with a single parameter: + * the custom object parameter, if provided.

    + * + * @method onContentReady + * + * @param {string} id the id of the element to look for. + * @param {function} fn what to execute when the element is ready. + * @param {object} obj an optional object to be passed back as + * a parameter to fn. + * @param {boolean|object} overrideContext If set to true, fn will execute + * in the context of obj. If an object, fn will + * exectute in the context of that object + * + * @static + */ + onContentReady: function(id, fn, obj, overrideContext) { + this.onAvailable(id, fn, obj, overrideContext, true); + }, + + /** + * Executes the supplied callback when the DOM is first usable. This + * will execute immediately if called after the DOMReady event has + * fired. @todo the DOMContentReady event does not fire when the + * script is dynamically injected into the page. This means the + * DOMReady custom event will never fire in FireFox or Opera when the + * library is injected. It _will_ fire in Safari, and the IE + * implementation would allow for us to fire it if the defered script + * is not available. We want this to behave the same in all browsers. + * Is there a way to identify when the script has been injected + * instead of included inline? Is there a way to know whether the + * window onload event has fired without having had a listener attached + * to it when it did so? + * + *

    The callback is a CustomEvent, so the signature is:

    + *

    type <string>, args <array>, customobject <object>

    + *

    For DOMReady events, there are no fire argments, so the + * signature is:

    + *

    "DOMReady", [], obj

    + * + * + * @method onDOMReady + * + * @param {function} fn what to execute when the element is found. + * @param {object} obj an optional object to be passed back as + * a parameter to fn. + * @param {boolean|object} overrideContext If set to true, fn will execute + * in the context of obj, if set to an object it + * will execute in the context of that object + * + * @static + */ + // onDOMReady: function(fn, obj, overrideContext) { + onDOMReady: function() { + this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent, arguments); + }, + + + /** + * Appends an event handler + * + * @method _addListener + * + * @param {String|HTMLElement|Array|NodeList} el An id, an element + * reference, or a collection of ids and/or elements to assign the + * listener to. + * @param {String} sType The type of event to append + * @param {Function} fn The method the event invokes + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the handler + * @param {Boolean|object} overrideContext If true, the obj passed in becomes + * the execution context of the listener. If an + * object, this object becomes the execution + * context. + * @param {boolen} capture capture or bubble phase + * @return {Boolean} True if the action was successful or defered, + * false if one or more of the elements + * could not have the listener attached, + * or if the operation throws an exception. + * @private + * @static + */ + _addListener: function(el, sType, fn, obj, overrideContext, bCapture) { + + if (!fn || !fn.call) { + return false; + } + + // The el argument can be an array of elements or element ids. + if ( this._isValidCollection(el)) { + var ok = true; + for (var i=0,len=el.length; i-1; i--) { + ok = ( this.removeListener(el[i], sType, fn) && ok ); + } + return ok; + } + + if (!fn || !fn.call) { + //return false; + return this.purgeElement(el, false, sType); + } + + if ("unload" == sType) { + + for (i=unloadListeners.length-1; i>-1; i--) { + li = unloadListeners[i]; + if (li && + li[0] == el && + li[1] == sType && + li[2] == fn) { + unloadListeners.splice(i, 1); + // unloadListeners[i]=null; + return true; + } + } + + return false; + } + + var cacheItem = null; + + // The index is a hidden parameter; needed to remove it from + // the method signature because it was tempting users to + // try and take advantage of it, which is not possible. + var index = arguments[3]; + + if ("undefined" === typeof index) { + index = this._getCacheIndex(listeners, el, sType, fn); + } + + if (index >= 0) { + cacheItem = listeners[index]; + } + + if (!el || !cacheItem) { + return false; + } + + + var bCapture = cacheItem[this.CAPTURE] === true ? true : false; + + try { + this._simpleRemove(el, sType, cacheItem[this.WFN], bCapture); + } catch(ex) { + this.lastError = ex; + return false; + } + + // removed the wrapped handler + delete listeners[index][this.WFN]; + delete listeners[index][this.FN]; + listeners.splice(index, 1); + // listeners[index]=null; + + return true; + + }, + + /** + * Returns the event's target element. Safari sometimes provides + * a text node, and this is automatically resolved to the text + * node's parent so that it behaves like other browsers. + * @method getTarget + * @param {Event} ev the event + * @param {boolean} resolveTextNode when set to true the target's + * parent will be returned if the target is a + * text node. @deprecated, the text node is + * now resolved automatically + * @return {HTMLElement} the event's target + * @static + */ + getTarget: function(ev, resolveTextNode) { + var t = ev.target || ev.srcElement; + return this.resolveTextNode(t); + }, + + /** + * In some cases, some browsers will return a text node inside + * the actual element that was targeted. This normalizes the + * return value for getTarget and getRelatedTarget. + * + * If accessing a property of the node throws an error, this is + * probably the anonymous div wrapper Gecko adds inside text + * nodes. This likely will only occur when attempting to access + * the relatedTarget. In this case, we now return null because + * the anonymous div is completely useless and we do not know + * what the related target was because we can't even get to + * the element's parent node. + * + * @method resolveTextNode + * @param {HTMLElement} node node to resolve + * @return {HTMLElement} the normized node + * @static + */ + resolveTextNode: function(n) { + try { + if (n && 3 == n.nodeType) { + return n.parentNode; + } + } catch(e) { + return null; + } + + return n; + }, + + /** + * Returns the event's pageX + * @method getPageX + * @param {Event} ev the event + * @return {int} the event's pageX + * @static + */ + getPageX: function(ev) { + var x = ev.pageX; + if (!x && 0 !== x) { + x = ev.clientX || 0; + + if ( this.isIE ) { + x += this._getScrollLeft(); + } + } + + return x; + }, + + /** + * Returns the event's pageY + * @method getPageY + * @param {Event} ev the event + * @return {int} the event's pageY + * @static + */ + getPageY: function(ev) { + var y = ev.pageY; + if (!y && 0 !== y) { + y = ev.clientY || 0; + + if ( this.isIE ) { + y += this._getScrollTop(); + } + } + + + return y; + }, + + /** + * Returns the pageX and pageY properties as an indexed array. + * @method getXY + * @param {Event} ev the event + * @return {[x, y]} the pageX and pageY properties of the event + * @static + */ + getXY: function(ev) { + return [this.getPageX(ev), this.getPageY(ev)]; + }, + + /** + * Returns the event's related target + * @method getRelatedTarget + * @param {Event} ev the event + * @return {HTMLElement} the event's relatedTarget + * @static + */ + getRelatedTarget: function(ev) { + var t = ev.relatedTarget; + if (!t) { + if (ev.type == "mouseout") { + t = ev.toElement; + } else if (ev.type == "mouseover") { + t = ev.fromElement; + } + } + + return this.resolveTextNode(t); + }, + + /** + * Returns the time of the event. If the time is not included, the + * event is modified using the current time. + * @method getTime + * @param {Event} ev the event + * @return {Date} the time of the event + * @static + */ + getTime: function(ev) { + if (!ev.time) { + var t = new Date().getTime(); + try { + ev.time = t; + } catch(ex) { + this.lastError = ex; + return t; + } + } + + return ev.time; + }, + + /** + * Convenience method for stopPropagation + preventDefault + * @method stopEvent + * @param {Event} ev the event + * @static + */ + stopEvent: function(ev) { + this.stopPropagation(ev); + this.preventDefault(ev); + }, + + /** + * Stops event propagation + * @method stopPropagation + * @param {Event} ev the event + * @static + */ + stopPropagation: function(ev) { + if (ev.stopPropagation) { + ev.stopPropagation(); + } else { + ev.cancelBubble = true; + } + }, + + /** + * Prevents the default behavior of the event + * @method preventDefault + * @param {Event} ev the event + * @static + */ + preventDefault: function(ev) { + if (ev.preventDefault) { + ev.preventDefault(); + } else { + ev.returnValue = false; + } + }, + + /** + * Finds the event in the window object, the caller's arguments, or + * in the arguments of another method in the callstack. This is + * executed automatically for events registered through the event + * manager, so the implementer should not normally need to execute + * this function at all. + * @method getEvent + * @param {Event} e the event parameter from the handler + * @param {HTMLElement} boundEl the element the listener is attached to + * @return {Event} the event + * @static + */ + getEvent: function(e, boundEl) { + var ev = e || window.event; + + if (!ev) { + var c = this.getEvent.caller; + while (c) { + ev = c.arguments[0]; + if (ev && Event == ev.constructor) { + break; + } + c = c.caller; + } + } + + return ev; + }, + + /** + * Returns the charcode for an event + * @method getCharCode + * @param {Event} ev the event + * @return {int} the event's charCode + * @static + */ + getCharCode: function(ev) { + var code = ev.keyCode || ev.charCode || 0; + + // webkit key normalization + if (YAHOO.env.ua.webkit && (code in webkitKeymap)) { + code = webkitKeymap[code]; + } + return code; + }, + + /** + * Locating the saved event handler data by function ref + * + * @method _getCacheIndex + * @static + * @private + */ + _getCacheIndex: function(a, el, sType, fn) { + for (var i=0, l=a.length; i 0 && onAvailStack.length > 0); + } + + // onAvailable + var notAvail = []; + + var executeItem = function (el, item) { + var context = el; + if (item.overrideContext) { + if (item.overrideContext === true) { + context = item.obj; + } else { + context = item.overrideContext; + } + } + item.fn.call(context, item.obj); + }; + + var i, len, item, el, ready=[]; + + // onAvailable onContentReady + for (i=0, len=onAvailStack.length; i-1; i--) { + item = onAvailStack[i]; + if (!item || !item.id) { + onAvailStack.splice(i, 1); + } + } + + this.startInterval(); + } else { + if (this._interval) { + // clearInterval(this._interval); + this._interval.cancel(); + this._interval = null; + } + } + + this.locked = false; + + }, + + /** + * Removes all listeners attached to the given element via addListener. + * Optionally, the node's children can also be purged. + * Optionally, you can specify a specific type of event to remove. + * @method purgeElement + * @param {HTMLElement} el the element to purge + * @param {boolean} recurse recursively purge this element's children + * as well. Use with caution. + * @param {string} sType optional type of listener to purge. If + * left out, all listeners will be removed + * @static + */ + purgeElement: function(el, recurse, sType) { + var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el; + var elListeners = this.getListeners(oEl, sType), i, len; + if (elListeners) { + for (i=elListeners.length-1; i>-1; i--) { + var l = elListeners[i]; + this.removeListener(oEl, l.type, l.fn); + } + } + + if (recurse && oEl && oEl.childNodes) { + for (i=0,len=oEl.childNodes.length; i-1; j--) { + l = listeners[j]; + if (l) { + try { + EU.removeListener(l[EU.EL], l[EU.TYPE], l[EU.FN], j); + } catch(e2) {} + } + } + l=null; + } + + try { + EU._simpleRemove(window, "unload", EU._unload); + EU._simpleRemove(window, "load", EU._load); + } catch(e3) {} + + }, + + /** + * Returns scrollLeft + * @method _getScrollLeft + * @static + * @private + */ + _getScrollLeft: function() { + return this._getScroll()[1]; + }, + + /** + * Returns scrollTop + * @method _getScrollTop + * @static + * @private + */ + _getScrollTop: function() { + return this._getScroll()[0]; + }, + + /** + * Returns the scrollTop and scrollLeft. Used to calculate the + * pageX and pageY in Internet Explorer + * @method _getScroll + * @static + * @private + */ + _getScroll: function() { + var dd = document.documentElement, db = document.body; + if (dd && (dd.scrollTop || dd.scrollLeft)) { + return [dd.scrollTop, dd.scrollLeft]; + } else if (db) { + return [db.scrollTop, db.scrollLeft]; + } else { + return [0, 0]; + } + }, + + /** + * Used by old versions of CustomEvent, restored for backwards + * compatibility + * @method regCE + * @private + * @static + * @deprecated still here for backwards compatibility + */ + regCE: function() {}, + + /** + * Adds a DOM event directly without the caching, cleanup, context adj, etc + * + * @method _simpleAdd + * @param {HTMLElement} el the element to bind the handler to + * @param {string} sType the type of event handler + * @param {function} fn the callback to invoke + * @param {boolen} capture capture or bubble phase + * @static + * @private + */ + _simpleAdd: function () { + if (window.addEventListener) { + return function(el, sType, fn, capture) { + el.addEventListener(sType, fn, (capture)); + }; + } else if (window.attachEvent) { + return function(el, sType, fn, capture) { + el.attachEvent("on" + sType, fn); + }; + } else { + return function(){}; + } + }(), + + /** + * Basic remove listener + * + * @method _simpleRemove + * @param {HTMLElement} el the element to bind the handler to + * @param {string} sType the type of event handler + * @param {function} fn the callback to invoke + * @param {boolen} capture capture or bubble phase + * @static + * @private + */ + _simpleRemove: function() { + if (window.removeEventListener) { + return function (el, sType, fn, capture) { + el.removeEventListener(sType, fn, (capture)); + }; + } else if (window.detachEvent) { + return function (el, sType, fn) { + el.detachEvent("on" + sType, fn); + }; + } else { + return function(){}; + } + }() + }; + + }(); + + (function() { + var EU = YAHOO.util.Event; + + /** + * Appends an event handler. This is an alias for addListener + * + * @method on + * + * @param {String|HTMLElement|Array|NodeList} el An id, an element + * reference, or a collection of ids and/or elements to assign the + * listener to. + * @param {String} sType The type of event to append + * @param {Function} fn The method the event invokes + * @param {Object} obj An arbitrary object that will be + * passed as a parameter to the handler + * @param {Boolean|object} overrideContext If true, the obj passed in becomes + * the execution context of the listener. If an + * object, this object becomes the execution + * context. + * @return {Boolean} True if the action was successful or defered, + * false if one or more of the elements + * could not have the listener attached, + * or if the operation throws an exception. + * @static + */ + EU.on = EU.addListener; + + /** + * YAHOO.util.Event.onFocus is an alias for addFocusListener + * @method onFocus + * @see addFocusListener + * @static + * @deprecated use YAHOO.util.Event.on and specify "focusin" as the event type. + */ + EU.onFocus = EU.addFocusListener; + + /** + * YAHOO.util.Event.onBlur is an alias for addBlurListener + * @method onBlur + * @see addBlurListener + * @static + * @deprecated use YAHOO.util.Event.on and specify "focusout" as the event type. + */ + EU.onBlur = EU.addBlurListener; + +/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ + + // Internet Explorer: use the readyState of a defered script. + // This isolates what appears to be a safe moment to manipulate + // the DOM prior to when the document's readyState suggests + // it is safe to do so. + if (EU.isIE) { + if (self !== self.top) { + document.onreadystatechange = function() { + if (document.readyState == 'complete') { + document.onreadystatechange = null; + EU._ready(); + } + }; + } else { + + // Process onAvailable/onContentReady items when the + // DOM is ready. + YAHOO.util.Event.onDOMReady( + YAHOO.util.Event._tryPreloadAttach, + YAHOO.util.Event, true); + + var n = document.createElement('p'); + + EU._dri = setInterval(function() { + try { + // throws an error if doc is not ready + n.doScroll('left'); + clearInterval(EU._dri); + EU._dri = null; + EU._ready(); + n = null; + } catch (ex) { + } + }, EU.POLL_INTERVAL); + } + + // The document's readyState in Safari currently will + // change to loaded/complete before images are loaded. + } else if (EU.webkit && EU.webkit < 525) { + + EU._dri = setInterval(function() { + var rs=document.readyState; + if ("loaded" == rs || "complete" == rs) { + clearInterval(EU._dri); + EU._dri = null; + EU._ready(); + } + }, EU.POLL_INTERVAL); + + // FireFox and Opera: These browsers provide a event for this + // moment. The latest WebKit releases now support this event. + } else { + + EU._simpleAdd(document, "DOMContentLoaded", EU._ready); + + } + ///////////////////////////////////////////////////////////// + + + EU._simpleAdd(window, "load", EU._load); + EU._simpleAdd(window, "unload", EU._unload); + EU._tryPreloadAttach(); + })(); + +} +/** + * EventProvider is designed to be used with YAHOO.augment to wrap + * CustomEvents in an interface that allows events to be subscribed to + * and fired by name. This makes it possible for implementing code to + * subscribe to an event that either has not been created yet, or will + * not be created at all. + * + * @Class EventProvider + */ +YAHOO.util.EventProvider = function() { }; + +YAHOO.util.EventProvider.prototype = { + + /** + * Private storage of custom events + * @property __yui_events + * @type Object[] + * @private + */ + __yui_events: null, + + /** + * Private storage of custom event subscribers + * @property __yui_subscribers + * @type Object[] + * @private + */ + __yui_subscribers: null, + + /** + * Subscribe to a CustomEvent by event type + * + * @method subscribe + * @param p_type {string} the type, or name of the event + * @param p_fn {function} the function to exectute when the event fires + * @param p_obj {Object} An object to be passed along when the event + * fires + * @param overrideContext {boolean} If true, the obj passed in becomes the + * execution scope of the listener + */ + subscribe: function(p_type, p_fn, p_obj, overrideContext) { + + this.__yui_events = this.__yui_events || {}; + var ce = this.__yui_events[p_type]; + + if (ce) { + ce.subscribe(p_fn, p_obj, overrideContext); + } else { + this.__yui_subscribers = this.__yui_subscribers || {}; + var subs = this.__yui_subscribers; + if (!subs[p_type]) { + subs[p_type] = []; + } + subs[p_type].push( + { fn: p_fn, obj: p_obj, overrideContext: overrideContext } ); + } + }, + + /** + * Unsubscribes one or more listeners the from the specified event + * @method unsubscribe + * @param p_type {string} The type, or name of the event. If the type + * is not specified, it will attempt to remove + * the listener from all hosted events. + * @param p_fn {Function} The subscribed function to unsubscribe, if not + * supplied, all subscribers will be removed. + * @param p_obj {Object} The custom object passed to subscribe. This is + * optional, but if supplied will be used to + * disambiguate multiple listeners that are the same + * (e.g., you subscribe many object using a function + * that lives on the prototype) + * @return {boolean} true if the subscriber was found and detached. + */ + unsubscribe: function(p_type, p_fn, p_obj) { + this.__yui_events = this.__yui_events || {}; + var evts = this.__yui_events; + if (p_type) { + var ce = evts[p_type]; + if (ce) { + return ce.unsubscribe(p_fn, p_obj); + } + } else { + var ret = true; + for (var i in evts) { + if (YAHOO.lang.hasOwnProperty(evts, i)) { + ret = ret && evts[i].unsubscribe(p_fn, p_obj); + } + } + return ret; + } + + return false; + }, + + /** + * Removes all listeners from the specified event. If the event type + * is not specified, all listeners from all hosted custom events will + * be removed. + * @method unsubscribeAll + * @param p_type {string} The type, or name of the event + */ + unsubscribeAll: function(p_type) { + return this.unsubscribe(p_type); + }, + + /** + * Creates a new custom event of the specified type. If a custom event + * by that name already exists, it will not be re-created. In either + * case the custom event is returned. + * + * @method createEvent + * + * @param p_type {string} the type, or name of the event + * @param p_config {object} optional config params. Valid properties are: + * + *
      + *
    • + * scope: defines the default execution scope. If not defined + * the default scope will be this instance. + *
    • + *
    • + * silent: if true, the custom event will not generate log messages. + * This is false by default. + *
    • + *
    • + * fireOnce: if true, the custom event will only notify subscribers + * once regardless of the number of times the event is fired. In + * addition, new subscribers will be executed immediately if the + * event has already fired. + * This is false by default. + *
    • + *
    • + * onSubscribeCallback: specifies a callback to execute when the + * event has a new subscriber. This will fire immediately for + * each queued subscriber if any exist prior to the creation of + * the event. + *
    • + *
    + * + * @return {CustomEvent} the custom event + * + */ + createEvent: function(p_type, p_config) { + + this.__yui_events = this.__yui_events || {}; + var opts = p_config || {}, + events = this.__yui_events, ce; + + if (events[p_type]) { + } else { + + ce = new YAHOO.util.CustomEvent(p_type, opts.scope || this, opts.silent, + YAHOO.util.CustomEvent.FLAT, opts.fireOnce); + + events[p_type] = ce; + + if (opts.onSubscribeCallback) { + ce.subscribeEvent.subscribe(opts.onSubscribeCallback); + } + + this.__yui_subscribers = this.__yui_subscribers || {}; + var qs = this.__yui_subscribers[p_type]; + + if (qs) { + for (var i=0; i + *
  • The first argument fire() was executed with
  • + *
  • The custom object (if any) that was passed into the subscribe() + * method
  • + * + * @method fireEvent + * @param p_type {string} the type, or name of the event + * @param arguments {Object*} an arbitrary set of parameters to pass to + * the handler. + * @return {boolean} the return value from CustomEvent.fire + * + */ + fireEvent: function(p_type) { + + this.__yui_events = this.__yui_events || {}; + var ce = this.__yui_events[p_type]; + + if (!ce) { + return null; + } + + var args = []; + for (var i=1; i 0) { + // Substring until first space + sClass = sSource.substring(0,spaceIndex); + // The rest of the source + sDetail = sSource.substring(spaceIndex,sSource.length); + } + else { + sClass = sSource; + } + if(this._isNewSource(sClass)) { + this._createNewSource(sClass); + } + } + + var timestamp = new Date(); + var logEntry = new YAHOO.widget.LogMsg({ + msg: sMsg, + time: timestamp, + category: sCategory, + source: sClass, + sourceDetail: sDetail + }); + + var stack = this._stack; + var maxStackEntries = this.maxStackEntries; + if(maxStackEntries && !isNaN(maxStackEntries) && + (stack.length >= maxStackEntries)) { + stack.shift(); + } + stack.push(logEntry); + this.newLogEvent.fire(logEntry); + + if(this._browserConsoleEnabled) { + this._printToBrowserConsole(logEntry); + } + return true; + } + else { + return false; + } + }; + + /** + * Resets internal stack and startTime, enables Logger, and fires logResetEvent. + * + * @method reset + */ + YAHOO.widget.Logger.reset = function() { + this._stack = []; + this._startTime = new Date().getTime(); + this.loggerEnabled = true; + this.log("Logger reset"); + this.logResetEvent.fire(); + }; + + /** + * Public accessor to internal stack of log message objects. + * + * @method getStack + * @return {Object[]} Array of log message objects. + */ + YAHOO.widget.Logger.getStack = function() { + return this._stack; + }; + + /** + * Public accessor to internal start time. + * + * @method getStartTime + * @return {Date} Internal date of when Logger singleton was initialized. + */ + YAHOO.widget.Logger.getStartTime = function() { + return this._startTime; + }; + + /** + * Disables output to the browser's global console.log() function, which is used + * by the Firebug extension to Firefox as well as Safari. + * + * @method disableBrowserConsole + */ + YAHOO.widget.Logger.disableBrowserConsole = function() { + YAHOO.log("Logger output to the function console.log() has been disabled."); + this._browserConsoleEnabled = false; + }; + + /** + * Enables output to the browser's global console.log() function, which is used + * by the Firebug extension to Firefox as well as Safari. + * + * @method enableBrowserConsole + */ + YAHOO.widget.Logger.enableBrowserConsole = function() { + this._browserConsoleEnabled = true; + YAHOO.log("Logger output to the function console.log() has been enabled."); + }; + + /** + * Surpresses native JavaScript errors and outputs to console. By default, + * Logger does not handle JavaScript window error events. + * NB: Not all browsers support the window.onerror event. + * + * @method handleWindowErrors + */ + YAHOO.widget.Logger.handleWindowErrors = function() { + if(!YAHOO.widget.Logger._windowErrorsHandled) { + // Save any previously defined handler to call + if(window.error) { + YAHOO.widget.Logger._origOnWindowError = window.onerror; + } + window.onerror = YAHOO.widget.Logger._onWindowError; + YAHOO.widget.Logger._windowErrorsHandled = true; + YAHOO.log("Logger handling of window.onerror has been enabled."); + } + else { + YAHOO.log("Logger handling of window.onerror had already been enabled."); + } + }; + + /** + * Unsurpresses native JavaScript errors. By default, + * Logger does not handle JavaScript window error events. + * NB: Not all browsers support the window.onerror event. + * + * @method unhandleWindowErrors + */ + YAHOO.widget.Logger.unhandleWindowErrors = function() { + if(YAHOO.widget.Logger._windowErrorsHandled) { + // Revert to any previously defined handler to call + if(YAHOO.widget.Logger._origOnWindowError) { + window.onerror = YAHOO.widget.Logger._origOnWindowError; + YAHOO.widget.Logger._origOnWindowError = null; + } + else { + window.onerror = null; + } + YAHOO.widget.Logger._windowErrorsHandled = false; + YAHOO.log("Logger handling of window.onerror has been disabled."); + } + else { + YAHOO.log("Logger handling of window.onerror had already been disabled."); + } + }; + + ///////////////////////////////////////////////////////////////////////////// + // + // Public events + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Fired when a new category has been created. + * + * @event categoryCreateEvent + * @param sCategory {String} Category name. + */ + YAHOO.widget.Logger.categoryCreateEvent = + new YAHOO.util.CustomEvent("categoryCreate", this, true); + + /** + * Fired when a new source has been named. + * + * @event sourceCreateEvent + * @param sSource {String} Source name. + */ + YAHOO.widget.Logger.sourceCreateEvent = + new YAHOO.util.CustomEvent("sourceCreate", this, true); + + /** + * Fired when a new log message has been created. + * + * @event newLogEvent + * @param sMsg {String} Log message. + */ + YAHOO.widget.Logger.newLogEvent = new YAHOO.util.CustomEvent("newLog", this, true); + + /** + * Fired when the Logger has been reset has been created. + * + * @event logResetEvent + */ + YAHOO.widget.Logger.logResetEvent = new YAHOO.util.CustomEvent("logReset", this, true); + + ///////////////////////////////////////////////////////////////////////////// + // + // Private methods + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Creates a new category of log messages and fires categoryCreateEvent. + * + * @method _createNewCategory + * @param sCategory {String} Category name. + * @private + */ + YAHOO.widget.Logger._createNewCategory = function(sCategory) { + this.categories.push(sCategory); + this.categoryCreateEvent.fire(sCategory); + }; + + /** + * Checks to see if a category has already been created. + * + * @method _isNewCategory + * @param sCategory {String} Category name. + * @return {Boolean} Returns true if category is unknown, else returns false. + * @private + */ + YAHOO.widget.Logger._isNewCategory = function(sCategory) { + for(var i=0; i < this.categories.length; i++) { + if(sCategory == this.categories[i]) { + return false; + } + } + return true; + }; + + /** + * Creates a new source of log messages and fires sourceCreateEvent. + * + * @method _createNewSource + * @param sSource {String} Source name. + * @private + */ + YAHOO.widget.Logger._createNewSource = function(sSource) { + this.sources.push(sSource); + this.sourceCreateEvent.fire(sSource); + }; + + /** + * Checks to see if a source already exists. + * + * @method _isNewSource + * @param sSource {String} Source name. + * @return {Boolean} Returns true if source is unknown, else returns false. + * @private + */ + YAHOO.widget.Logger._isNewSource = function(sSource) { + if(sSource) { + for(var i=0; i < this.sources.length; i++) { + if(sSource == this.sources[i]) { + return false; + } + } + return true; + } + }; + + /** + * Outputs a log message to global console.log() function. + * + * @method _printToBrowserConsole + * @param oEntry {Object} Log entry object. + * @private + */ + YAHOO.widget.Logger._printToBrowserConsole = function(oEntry) { + if ((window.console && console.log) || + (window.opera && opera.postError)) { + var category = oEntry.category; + var label = oEntry.category.substring(0,4).toUpperCase(); + + var time = oEntry.time; + var localTime; + if (time.toLocaleTimeString) { + localTime = time.toLocaleTimeString(); + } + else { + localTime = time.toString(); + } + + var msecs = time.getTime(); + var elapsedTime = (YAHOO.widget.Logger._lastTime) ? + (msecs - YAHOO.widget.Logger._lastTime) : 0; + YAHOO.widget.Logger._lastTime = msecs; + + var output = + localTime + " (" + + elapsedTime + "ms): " + + oEntry.source + ": "; + + if (window.console) { + console.log(output, oEntry.msg); + } else { + opera.postError(output + oEntry.msg); + } + } + }; + + ///////////////////////////////////////////////////////////////////////////// + // + // Private event handlers + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Handles logging of messages due to window error events. + * + * @method _onWindowError + * @param sMsg {String} The error message. + * @param sUrl {String} URL of the error. + * @param sLine {String} Line number of the error. + * @private + */ + YAHOO.widget.Logger._onWindowError = function(sMsg,sUrl,sLine) { + // Logger is not in scope of this event handler + try { + YAHOO.widget.Logger.log(sMsg+' ('+sUrl+', line '+sLine+')', "window"); + if(YAHOO.widget.Logger._origOnWindowError) { + YAHOO.widget.Logger._origOnWindowError(); + } + } + catch(e) { + return false; + } + }; + + ///////////////////////////////////////////////////////////////////////////// + // + // First log + // + ///////////////////////////////////////////////////////////////////////////// + + YAHOO.widget.Logger.log("Logger initialized"); +} + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +(function () { +var Logger = YAHOO.widget.Logger, + u = YAHOO.util, + Dom = u.Dom, + Event = u.Event, + d = document; + +function make(el,props) { + el = d.createElement(el); + if (props) { + for (var p in props) { + if (props.hasOwnProperty(p)) { + el[p] = props[p]; + } + } + } + return el; +} + +/** + * The LogReader class provides UI to read messages logged to YAHOO.widget.Logger. + * + * @class LogReader + * @constructor + * @param elContainer {HTMLElement} (optional) DOM element reference of an existing DIV. + * @param elContainer {String} (optional) String ID of an existing DIV. + * @param oConfigs {Object} (optional) Object literal of configuration params. + */ +function LogReader(elContainer, oConfigs) { + this._sName = LogReader._index; + LogReader._index++; + + this._init.apply(this,arguments); + + /** + * Render the LogReader immediately upon instantiation. If set to false, + * you must call myLogReader.render() to generate the UI. + * + * @property autoRender + * @type {Boolean} + * @default true + */ + if (this.autoRender !== false) { + this.render(); + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// Static member variables +// +///////////////////////////////////////////////////////////////////////////// +YAHOO.lang.augmentObject(LogReader, { + /** + * Internal class member to index multiple LogReader instances. + * + * @property _memberName + * @static + * @type Number + * @default 0 + * @private + */ + _index : 0, + + /** + * Node template for the log entries + * @property ENTRY_TEMPLATE + * @static + * @type {HTMLElement} + * @default pre element with class yui-log-entry + */ + ENTRY_TEMPLATE : (function () { + return make('pre',{ className: 'yui-log-entry' }); + })(), + + /** + * Template used for innerHTML of verbose entry output. + * @property VERBOSE_TEMPLATE + * @static + * @default "<p><span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}:</p><p>{sourceAndDetail}</p><p>{message}</p>" + */ + VERBOSE_TEMPLATE : "

    {label} {totalTime}ms (+{elapsedTime}) {localTime}:

    {sourceAndDetail}

    {message}

    ", + + /** + * Template used for innerHTML of compact entry output. + * @property BASIC_TEMPLATE + * @static + * @default "<p><span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}</p>" + */ + BASIC_TEMPLATE : "

    {label} {totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}

    " +}); + +///////////////////////////////////////////////////////////////////////////// +// +// Public member variables +// +///////////////////////////////////////////////////////////////////////////// + +LogReader.prototype = { + /** + * Whether or not LogReader is enabled to output log messages. + * + * @property logReaderEnabled + * @type Boolean + * @default true + */ + logReaderEnabled : true, + + /** + * Public member to access CSS width of the LogReader container. + * + * @property width + * @type String + */ + width : null, + + /** + * Public member to access CSS height of the LogReader container. + * + * @property height + * @type String + */ + height : null, + + /** + * Public member to access CSS top position of the LogReader container. + * + * @property top + * @type String + */ + top : null, + + /** + * Public member to access CSS left position of the LogReader container. + * + * @property left + * @type String + */ + left : null, + + /** + * Public member to access CSS right position of the LogReader container. + * + * @property right + * @type String + */ + right : null, + + /** + * Public member to access CSS bottom position of the LogReader container. + * + * @property bottom + * @type String + */ + bottom : null, + + /** + * Public member to access CSS font size of the LogReader container. + * + * @property fontSize + * @type String + */ + fontSize : null, + + /** + * Whether or not the footer UI is enabled for the LogReader. + * + * @property footerEnabled + * @type Boolean + * @default true + */ + footerEnabled : true, + + /** + * Whether or not output is verbose (more readable). Setting to true will make + * output more compact (less readable). + * + * @property verboseOutput + * @type Boolean + * @default true + */ + verboseOutput : true, + + /** + * Custom output format for log messages. Defaults to null, which falls + * back to verboseOutput param deciding between LogReader.VERBOSE_TEMPLATE + * and LogReader.BASIC_TEMPLATE. Use bracketed place holders to mark where + * message info should go. Available place holder names include: + *
      + *
    • category
    • + *
    • label
    • + *
    • sourceAndDetail
    • + *
    • message
    • + *
    • localTime
    • + *
    • elapsedTime
    • + *
    • totalTime
    • + *
    + * + * @property entryFormat + * @type String + * @default null + */ + entryFormat : null, + + /** + * Whether or not newest message is printed on top. + * + * @property newestOnTop + * @type Boolean + */ + newestOnTop : true, + + /** + * Output timeout buffer in milliseconds. + * + * @property outputBuffer + * @type Number + * @default 100 + */ + outputBuffer : 100, + + /** + * Maximum number of messages a LogReader console will display. + * + * @property thresholdMax + * @type Number + * @default 500 + */ + thresholdMax : 500, + + /** + * When a LogReader console reaches its thresholdMax, it will clear out messages + * and print out the latest thresholdMin number of messages. + * + * @property thresholdMin + * @type Number + * @default 100 + */ + thresholdMin : 100, + + /** + * True when LogReader is in a collapsed state, false otherwise. + * + * @property isCollapsed + * @type Boolean + * @default false + */ + isCollapsed : false, + + /** + * True when LogReader is in a paused state, false otherwise. + * + * @property isPaused + * @type Boolean + * @default false + */ + isPaused : false, + + /** + * Enables draggable LogReader if DragDrop Utility is present. + * + * @property draggable + * @type Boolean + * @default true + */ + draggable : true, + + ///////////////////////////////////////////////////////////////////////////// + // + // Public methods + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Public accessor to the unique name of the LogReader instance. + * + * @method toString + * @return {String} Unique name of the LogReader instance. + */ + toString : function() { + return "LogReader instance" + this._sName; + }, + /** + * Pauses output of log messages. While paused, log messages are not lost, but + * get saved to a buffer and then output upon resume of LogReader. + * + * @method pause + */ + pause : function() { + this.isPaused = true; + this._timeout = null; + this.logReaderEnabled = false; + if (this._btnPause) { + this._btnPause.value = "Resume"; + } + }, + + /** + * Resumes output of log messages, including outputting any log messages that + * have been saved to buffer while paused. + * + * @method resume + */ + resume : function() { + this.isPaused = false; + this.logReaderEnabled = true; + this._printBuffer(); + if (this._btnPause) { + this._btnPause.value = "Pause"; + } + }, + + /** + * Adds the UI to the DOM, attaches event listeners, and bootstraps initial + * UI state. + * + * @method render + */ + render : function () { + if (this.rendered) { + return; + } + + this._initContainerEl(); + + this._initHeaderEl(); + this._initConsoleEl(); + this._initFooterEl(); + + this._initCategories(); + this._initSources(); + + this._initDragDrop(); + + // Subscribe to Logger custom events + Logger.newLogEvent.subscribe(this._onNewLog, this); + Logger.logResetEvent.subscribe(this._onReset, this); + + Logger.categoryCreateEvent.subscribe(this._onCategoryCreate, this); + Logger.sourceCreateEvent.subscribe(this._onSourceCreate, this); + + this.rendered = true; + + this._filterLogs(); + }, + + /** + * Removes the UI from the DOM entirely and detaches all event listeners. + * Implementers should note that Logger will still accumulate messages. + * + * @method destroy + */ + destroy : function () { + Event.purgeElement(this._elContainer,true); + this._elContainer.innerHTML = ''; + this._elContainer.parentNode.removeChild(this._elContainer); + + this.rendered = false; + }, + + /** + * Hides UI of LogReader. Logging functionality is not disrupted. + * + * @method hide + */ + hide : function() { + this._elContainer.style.display = "none"; + }, + + /** + * Shows UI of LogReader. Logging functionality is not disrupted. + * + * @method show + */ + show : function() { + this._elContainer.style.display = "block"; + }, + + /** + * Collapses UI of LogReader. Logging functionality is not disrupted. + * + * @method collapse + */ + collapse : function() { + this._elConsole.style.display = "none"; + if(this._elFt) { + this._elFt.style.display = "none"; + } + this._btnCollapse.value = "Expand"; + this.isCollapsed = true; + }, + + /** + * Expands UI of LogReader. Logging functionality is not disrupted. + * + * @method expand + */ + expand : function() { + this._elConsole.style.display = "block"; + if(this._elFt) { + this._elFt.style.display = "block"; + } + this._btnCollapse.value = "Collapse"; + this.isCollapsed = false; + }, + + /** + * Returns related checkbox element for given filter (i.e., category or source). + * + * @method getCheckbox + * @param {String} Category or source name. + * @return {Array} Array of all filter checkboxes. + */ + getCheckbox : function(filter) { + return this._filterCheckboxes[filter]; + }, + + /** + * Returns array of enabled categories. + * + * @method getCategories + * @return {String[]} Array of enabled categories. + */ + getCategories : function() { + return this._categoryFilters; + }, + + /** + * Shows log messages associated with given category. + * + * @method showCategory + * @param {String} Category name. + */ + showCategory : function(sCategory) { + var filtersArray = this._categoryFilters; + // Don't do anything if category is already enabled + // Use Array.indexOf if available... + if(filtersArray.indexOf) { + if(filtersArray.indexOf(sCategory) > -1) { + return; + } + } + // ...or do it the old-fashioned way + else { + for(var i=0; i -1) { + return; + } + } + // ...or do it the old-fashioned way + else { + for(var i=0; i", and "&" to HTML entities. + * + * @method html2Text + * @param sHtml {String} String to convert. + * @private + */ + html2Text : function(sHtml) { + if(sHtml) { + sHtml += ""; + return sHtml.replace(/&/g, "&"). + replace(//g, ">"); + } + return ""; + }, + +///////////////////////////////////////////////////////////////////////////// +// +// Private member variables +// +///////////////////////////////////////////////////////////////////////////// + + /** + * Name of LogReader instance. + * + * @property _sName + * @type String + * @private + */ + _sName : null, + + //TODO: remove + /** + * A class member shared by all LogReaders if a container needs to be + * created during instantiation. Will be null if a container element never needs to + * be created on the fly, such as when the implementer passes in their own element. + * + * @property _elDefaultContainer + * @type HTMLElement + * @private + */ + //YAHOO.widget.LogReader._elDefaultContainer = null; + + /** + * Buffer of log message objects for batch output. + * + * @property _buffer + * @type Object[] + * @private + */ + _buffer : null, + + /** + * Number of log messages output to console. + * + * @property _consoleMsgCount + * @type Number + * @default 0 + * @private + */ + _consoleMsgCount : 0, + + /** + * Date of last output log message. + * + * @property _lastTime + * @type Date + * @private + */ + _lastTime : null, + + /** + * Batched output timeout ID. + * + * @property _timeout + * @type Number + * @private + */ + _timeout : null, + + /** + * Hash of filters and their related checkbox elements. + * + * @property _filterCheckboxes + * @type Object + * @private + */ + _filterCheckboxes : null, + + /** + * Array of filters for log message categories. + * + * @property _categoryFilters + * @type String[] + * @private + */ + _categoryFilters : null, + + /** + * Array of filters for log message sources. + * + * @property _sourceFilters + * @type String[] + * @private + */ + _sourceFilters : null, + + /** + * LogReader container element. + * + * @property _elContainer + * @type HTMLElement + * @private + */ + _elContainer : null, + + /** + * LogReader header element. + * + * @property _elHd + * @type HTMLElement + * @private + */ + _elHd : null, + + /** + * LogReader collapse element. + * + * @property _elCollapse + * @type HTMLElement + * @private + */ + _elCollapse : null, + + /** + * LogReader collapse button element. + * + * @property _btnCollapse + * @type HTMLElement + * @private + */ + _btnCollapse : null, + + /** + * LogReader title header element. + * + * @property _title + * @type HTMLElement + * @private + */ + _title : null, + + /** + * LogReader console element. + * + * @property _elConsole + * @type HTMLElement + * @private + */ + _elConsole : null, + + /** + * LogReader footer element. + * + * @property _elFt + * @type HTMLElement + * @private + */ + _elFt : null, + + /** + * LogReader buttons container element. + * + * @property _elBtns + * @type HTMLElement + * @private + */ + _elBtns : null, + + /** + * Container element for LogReader category filter checkboxes. + * + * @property _elCategoryFilters + * @type HTMLElement + * @private + */ + _elCategoryFilters : null, + + /** + * Container element for LogReader source filter checkboxes. + * + * @property _elSourceFilters + * @type HTMLElement + * @private + */ + _elSourceFilters : null, + + /** + * LogReader pause button element. + * + * @property _btnPause + * @type HTMLElement + * @private + */ + _btnPause : null, + + /** + * Clear button element. + * + * @property _btnClear + * @type HTMLElement + * @private + */ + _btnClear : null, + + ///////////////////////////////////////////////////////////////////////////// + // + // Private methods + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Initializes the instance's message buffer, start time, etc + * + * @method _init + * @param container {String|HTMLElement} (optional) the render target + * @param config {Object} (optional) instance configuration + * @protected + */ + _init : function (container, config) { + // Internal vars + this._buffer = []; // output buffer + this._filterCheckboxes = {}; // pointers to checkboxes + this._lastTime = Logger.getStartTime(); // timestamp of last log message to console + + // Parse config vars here + if (config && (config.constructor == Object)) { + for(var param in config) { + if (config.hasOwnProperty(param)) { + this[param] = config[param]; + } + } + } + + this._elContainer = Dom.get(container); + + YAHOO.log("LogReader initialized", null, this.toString()); + }, + + /** + * Initializes the primary container element. + * + * @method _initContainerEl + * @private + */ + _initContainerEl : function() { + + // Default the container if unset or not a div + if(!this._elContainer || !/div$/i.test(this._elContainer.tagName)) { + this._elContainer = d.body.insertBefore(make("div"),d.body.firstChild); + // Only position absolutely if an in-DOM element is not supplied + Dom.addClass(this._elContainer,"yui-log-container"); + } + + Dom.addClass(this._elContainer,"yui-log"); + + // If implementer has provided container values, trust and set those + var style = this._elContainer.style, + styleProps = ['width','right','top','fontSize'], + prop,i; + + for (i = styleProps.length - 1; i >= 0; --i) { + prop = styleProps[i]; + if (this[prop]){ + style[prop] = this[prop]; + } + } + + if(this.left) { + style.left = this.left; + style.right = "auto"; + } + if(this.bottom) { + style.bottom = this.bottom; + style.top = "auto"; + } + + // Opera needs a little prodding to reflow sometimes + if (YAHOO.env.ua.opera) { + d.body.style += ''; + } + + }, + + /** + * Initializes the header element. + * + * @method _initHeaderEl + * @private + */ + _initHeaderEl : function() { + // Destroy header if present + if(this._elHd) { + // Unhook DOM events + Event.purgeElement(this._elHd, true); + + // Remove DOM elements + this._elHd.innerHTML = ""; + } + + // Create header + // TODO: refactor this into an innerHTML + this._elHd = make("div",{ + className: "yui-log-hd" + }); + Dom.generateId(this._elHd, 'yui-log-hd' + this._sName); + + this._elCollapse = make("div",{ className: 'yui-log-btns' }); + + this._btnCollapse = make("input",{ + type: 'button', + className: 'yui-log-button', + value: 'Collapse' + }); + Event.on(this._btnCollapse,'click',this._onClickCollapseBtn,this); + + + this._title = make("h4",{ innerHTML : "Logger Console" }); + + this._elCollapse.appendChild(this._btnCollapse); + this._elHd.appendChild(this._elCollapse); + this._elHd.appendChild(this._title); + this._elContainer.appendChild(this._elHd); + }, + + /** + * Initializes the console element. + * + * @method _initConsoleEl + * @private + */ + _initConsoleEl : function() { + // Destroy console + if(this._elConsole) { + // Unhook DOM events + Event.purgeElement(this._elConsole, true); + + // Remove DOM elements + this._elConsole.innerHTML = ""; + } + + // Ceate console + this._elConsole = make("div", { className: "yui-log-bd" }); + + // If implementer has provided console, trust and set those + if(this.height) { + this._elConsole.style.height = this.height; + } + + this._elContainer.appendChild(this._elConsole); + }, + + /** + * Initializes the footer element. + * + * @method _initFooterEl + * @private + */ + _initFooterEl : function() { + // Don't create footer elements if footer is disabled + if(this.footerEnabled) { + // Destroy console + if(this._elFt) { + // Unhook DOM events + Event.purgeElement(this._elFt, true); + + // Remove DOM elements + this._elFt.innerHTML = ""; + } + + // TODO: use innerHTML + this._elFt = make("div",{ className: "yui-log-ft" }); + this._elBtns = make("div", { className: "yui-log-btns" }); + this._btnPause = make("input", { + type: "button", + className: "yui-log-button", + value: "Pause" + }); + + Event.on(this._btnPause,'click',this._onClickPauseBtn,this); + + this._btnClear = make("input", { + type: "button", + className: "yui-log-button", + value: "Clear" + }); + + Event.on(this._btnClear,'click',this._onClickClearBtn,this); + + this._elCategoryFilters = make("div", { className: "yui-log-categoryfilters" }); + this._elSourceFilters = make("div", { className: "yui-log-sourcefilters" }); + + this._elBtns.appendChild(this._btnPause); + this._elBtns.appendChild(this._btnClear); + this._elFt.appendChild(this._elBtns); + this._elFt.appendChild(this._elCategoryFilters); + this._elFt.appendChild(this._elSourceFilters); + this._elContainer.appendChild(this._elFt); + } + }, + + /** + * Initializes Drag and Drop on the header element. + * + * @method _initDragDrop + * @private + */ + _initDragDrop : function() { + // If Drag and Drop utility is available... + // ...and draggable is true... + // ...then make the header draggable + if(u.DD && this.draggable && this._elHd) { + var ylog_dd = new u.DD(this._elContainer); + ylog_dd.setHandleElId(this._elHd.id); + //TODO: use class name + this._elHd.style.cursor = "move"; + } + }, + + /** + * Initializes category filters. + * + * @method _initCategories + * @private + */ + _initCategories : function() { + // Initialize category filters + this._categoryFilters = []; + var aInitialCategories = Logger.categories; + + for(var j=0; j < aInitialCategories.length; j++) { + var sCategory = aInitialCategories[j]; + + // Add category to the internal array of filters + this._categoryFilters.push(sCategory); + + // Add checkbox element if UI is enabled + if(this._elCategoryFilters) { + this._createCategoryCheckbox(sCategory); + } + } + }, + + /** + * Initializes source filters. + * + * @method _initSources + * @private + */ + _initSources : function() { + // Initialize source filters + this._sourceFilters = []; + var aInitialSources = Logger.sources; + + for(var j=0; j < aInitialSources.length; j++) { + var sSource = aInitialSources[j]; + + // Add source to the internal array of filters + this._sourceFilters.push(sSource); + + // Add checkbox element if UI is enabled + if(this._elSourceFilters) { + this._createSourceCheckbox(sSource); + } + } + }, + + /** + * Creates the UI for a category filter in the LogReader footer element. + * + * @method _createCategoryCheckbox + * @param sCategory {String} Category name. + * @private + */ + _createCategoryCheckbox : function(sCategory) { + if(this._elFt) { + var filter = make("span",{ className: "yui-log-filtergrp" }), + checkid = Dom.generateId(null, "yui-log-filter-" + sCategory + this._sName), + check = make("input", { + id: checkid, + className: "yui-log-filter-" + sCategory, + type: "checkbox", + category: sCategory + }), + label = make("label", { + htmlFor: checkid, + className: sCategory, + innerHTML: sCategory + }); + + + // Subscribe to the click event + Event.on(check,'click',this._onCheckCategory,this); + + this._filterCheckboxes[sCategory] = check; + + // Append el at the end so IE 5.5 can set "type" attribute + // and THEN set checked property + filter.appendChild(check); + filter.appendChild(label); + this._elCategoryFilters.appendChild(filter); + check.checked = true; + } + }, + + /** + * Creates a checkbox in the LogReader footer element to filter by source. + * + * @method _createSourceCheckbox + * @param sSource {String} Source name. + * @private + */ + _createSourceCheckbox : function(sSource) { + if(this._elFt) { + var filter = make("span",{ className: "yui-log-filtergrp" }), + checkid = Dom.generateId(null, "yui-log-filter-" + sSource + this._sName), + check = make("input", { + id: checkid, + className: "yui-log-filter-" + sSource, + type: "checkbox", + source: sSource + }), + label = make("label", { + htmlFor: checkid, + className: sSource, + innerHTML: sSource + }); + + + // Subscribe to the click event + Event.on(check,'click',this._onCheckSource,this); + + this._filterCheckboxes[sSource] = check; + + // Append el at the end so IE 5.5 can set "type" attribute + // and THEN set checked property + filter.appendChild(check); + filter.appendChild(label); + this._elSourceFilters.appendChild(filter); + check.checked = true; + } + }, + + /** + * Reprints all log messages in the stack through filters. + * + * @method _filterLogs + * @private + */ + _filterLogs : function() { + // Reprint stack with new filters + if (this._elConsole !== null) { + this.clearConsole(); + this._printToConsole(Logger.getStack()); + } + }, + + /** + * Sends buffer of log messages to output and clears buffer. + * + * @method _printBuffer + * @private + */ + _printBuffer : function() { + this._timeout = null; + + if(this._elConsole !== null) { + var thresholdMax = this.thresholdMax; + thresholdMax = (thresholdMax && !isNaN(thresholdMax)) ? thresholdMax : 500; + if(this._consoleMsgCount < thresholdMax) { + var entries = []; + for (var i=0; i this.thresholdMax)) { + thresholdMin = 0; + } + entriesStartIndex = (entriesLen > thresholdMin) ? (entriesLen - thresholdMin) : 0; + + // Iterate through all log entries + for(i=entriesStartIndex; i0){c=g.substring(0,d);a=g.substring(d,g.length);}else{c=g;}if(this._isNewSource(c)){this._createNewSource(c);}}var h=new Date();var j=new YAHOO.widget.LogMsg({msg:b,time:h,category:f,source:c,sourceDetail:a});var i=this._stack;var e=this.maxStackEntries;if(e&&!isNaN(e)&&(i.length>=e)){i.shift();}i.push(j);this.newLogEvent.fire(j);if(this._browserConsoleEnabled){this._printToBrowserConsole(j);}return true;}else{return false;}};YAHOO.widget.Logger.reset=function(){this._stack=[];this._startTime=new Date().getTime();this.loggerEnabled=true;this.log("Logger reset");this.logResetEvent.fire();};YAHOO.widget.Logger.getStack=function(){return this._stack;};YAHOO.widget.Logger.getStartTime=function(){return this._startTime;};YAHOO.widget.Logger.disableBrowserConsole=function(){YAHOO.log("Logger output to the function console.log() has been disabled.");this._browserConsoleEnabled=false;};YAHOO.widget.Logger.enableBrowserConsole=function(){this._browserConsoleEnabled=true;YAHOO.log("Logger output to the function console.log() has been enabled.");};YAHOO.widget.Logger.handleWindowErrors=function(){if(!YAHOO.widget.Logger._windowErrorsHandled){if(window.error){YAHOO.widget.Logger._origOnWindowError=window.onerror;}window.onerror=YAHOO.widget.Logger._onWindowError;YAHOO.widget.Logger._windowErrorsHandled=true;YAHOO.log("Logger handling of window.onerror has been enabled.");}else{YAHOO.log("Logger handling of window.onerror had already been enabled.");}};YAHOO.widget.Logger.unhandleWindowErrors=function(){if(YAHOO.widget.Logger._windowErrorsHandled){if(YAHOO.widget.Logger._origOnWindowError){window.onerror=YAHOO.widget.Logger._origOnWindowError;YAHOO.widget.Logger._origOnWindowError=null;}else{window.onerror=null;}YAHOO.widget.Logger._windowErrorsHandled=false;YAHOO.log("Logger handling of window.onerror has been disabled.");}else{YAHOO.log("Logger handling of window.onerror had already been disabled.");}};YAHOO.widget.Logger.categoryCreateEvent=new YAHOO.util.CustomEvent("categoryCreate",this,true);YAHOO.widget.Logger.sourceCreateEvent=new YAHOO.util.CustomEvent("sourceCreate",this,true);YAHOO.widget.Logger.newLogEvent=new YAHOO.util.CustomEvent("newLog",this,true);YAHOO.widget.Logger.logResetEvent=new YAHOO.util.CustomEvent("logReset",this,true);YAHOO.widget.Logger._createNewCategory=function(a){this.categories.push(a);this.categoryCreateEvent.fire(a);};YAHOO.widget.Logger._isNewCategory=function(b){for(var a=0;a{label} {totalTime}ms (+{elapsedTime}) {localTime}:

    {sourceAndDetail}

    {message}

    ",BASIC_TEMPLATE:"

    {label} {totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}

    "});g.prototype={logReaderEnabled:true,width:null,height:null,top:null,left:null,right:null,bottom:null,fontSize:null,footerEnabled:true,verboseOutput:true,entryFormat:null,newestOnTop:true,outputBuffer:100,thresholdMax:500,thresholdMin:100,isCollapsed:false,isPaused:false,draggable:true,toString:function(){return"LogReader instance"+this._sName;},pause:function(){this.isPaused=true;this._timeout=null; +this.logReaderEnabled=false;if(this._btnPause){this._btnPause.value="Resume";}},resume:function(){this.isPaused=false;this.logReaderEnabled=true;this._printBuffer();if(this._btnPause){this._btnPause.value="Pause";}},render:function(){if(this.rendered){return;}this._initContainerEl();this._initHeaderEl();this._initConsoleEl();this._initFooterEl();this._initCategories();this._initSources();this._initDragDrop();c.newLogEvent.subscribe(this._onNewLog,this);c.logResetEvent.subscribe(this._onReset,this);c.categoryCreateEvent.subscribe(this._onCategoryCreate,this);c.sourceCreateEvent.subscribe(this._onSourceCreate,this);this.rendered=true;this._filterLogs();},destroy:function(){a.purgeElement(this._elContainer,true);this._elContainer.innerHTML="";this._elContainer.parentNode.removeChild(this._elContainer);this.rendered=false;},hide:function(){this._elContainer.style.display="none";},show:function(){this._elContainer.style.display="block";},collapse:function(){this._elConsole.style.display="none";if(this._elFt){this._elFt.style.display="none";}this._btnCollapse.value="Expand";this.isCollapsed=true;},expand:function(){this._elConsole.style.display="block";if(this._elFt){this._elFt.style.display="block";}this._btnCollapse.value="Collapse";this.isCollapsed=false;},getCheckbox:function(d){return this._filterCheckboxes[d];},getCategories:function(){return this._categoryFilters;},showCategory:function(j){var l=this._categoryFilters;if(l.indexOf){if(l.indexOf(j)>-1){return;}}else{for(var d=0;d-1){return;}}else{for(var j=0;j/g,">");}return"";},_sName:null,_buffer:null,_consoleMsgCount:0,_lastTime:null,_timeout:null,_filterCheckboxes:null,_categoryFilters:null,_sourceFilters:null,_elContainer:null,_elHd:null,_elCollapse:null,_btnCollapse:null,_title:null,_elConsole:null,_elFt:null,_elBtns:null,_elCategoryFilters:null,_elSourceFilters:null,_btnPause:null,_btnClear:null,_init:function(d,i){this._buffer=[];this._filterCheckboxes={};this._lastTime=c.getStartTime();if(i&&(i.constructor==Object)){for(var j in i){if(i.hasOwnProperty(j)){this[j]=i[j];}}}this._elContainer=f.get(d);YAHOO.log("LogReader initialized",null,this.toString());},_initContainerEl:function(){if(!this._elContainer||!/div$/i.test(this._elContainer.tagName)){this._elContainer=h.body.insertBefore(b("div"),h.body.firstChild);f.addClass(this._elContainer,"yui-log-container");}f.addClass(this._elContainer,"yui-log");var k=this._elContainer.style,d=["width","right","top","fontSize"],l,j;for(j=d.length-1;j>=0;--j){l=d[j];if(this[l]){k[l]=this[l];}}if(this.left){k.left=this.left;k.right="auto";}if(this.bottom){k.bottom=this.bottom;k.top="auto";}if(YAHOO.env.ua.opera){h.body.style+="";}},_initHeaderEl:function(){if(this._elHd){a.purgeElement(this._elHd,true);this._elHd.innerHTML="";}this._elHd=b("div",{className:"yui-log-hd"});f.generateId(this._elHd,"yui-log-hd"+this._sName);this._elCollapse=b("div",{className:"yui-log-btns"});this._btnCollapse=b("input",{type:"button",className:"yui-log-button",value:"Collapse"});a.on(this._btnCollapse,"click",this._onClickCollapseBtn,this);this._title=b("h4",{innerHTML:"Logger Console"});this._elCollapse.appendChild(this._btnCollapse);this._elHd.appendChild(this._elCollapse);this._elHd.appendChild(this._title);this._elContainer.appendChild(this._elHd);},_initConsoleEl:function(){if(this._elConsole){a.purgeElement(this._elConsole,true);this._elConsole.innerHTML="";}this._elConsole=b("div",{className:"yui-log-bd"});if(this.height){this._elConsole.style.height=this.height;}this._elContainer.appendChild(this._elConsole);},_initFooterEl:function(){if(this.footerEnabled){if(this._elFt){a.purgeElement(this._elFt,true);this._elFt.innerHTML="";}this._elFt=b("div",{className:"yui-log-ft"});this._elBtns=b("div",{className:"yui-log-btns"});this._btnPause=b("input",{type:"button",className:"yui-log-button",value:"Pause"});a.on(this._btnPause,"click",this._onClickPauseBtn,this);this._btnClear=b("input",{type:"button",className:"yui-log-button",value:"Clear"});a.on(this._btnClear,"click",this._onClickClearBtn,this);this._elCategoryFilters=b("div",{className:"yui-log-categoryfilters"});this._elSourceFilters=b("div",{className:"yui-log-sourcefilters"});this._elBtns.appendChild(this._btnPause);this._elBtns.appendChild(this._btnClear); +this._elFt.appendChild(this._elBtns);this._elFt.appendChild(this._elCategoryFilters);this._elFt.appendChild(this._elSourceFilters);this._elContainer.appendChild(this._elFt);}},_initDragDrop:function(){if(e.DD&&this.draggable&&this._elHd){var d=new e.DD(this._elContainer);d.setHandleElId(this._elHd.id);this._elHd.style.cursor="move";}},_initCategories:function(){this._categoryFilters=[];var k=c.categories;for(var d=0;dthis.thresholdMax)){z=0;}t=(k>z)?(k-z):0;for(q=t;q 0) { + // Substring until first space + sClass = sSource.substring(0,spaceIndex); + // The rest of the source + sDetail = sSource.substring(spaceIndex,sSource.length); + } + else { + sClass = sSource; + } + if(this._isNewSource(sClass)) { + this._createNewSource(sClass); + } + } + + var timestamp = new Date(); + var logEntry = new YAHOO.widget.LogMsg({ + msg: sMsg, + time: timestamp, + category: sCategory, + source: sClass, + sourceDetail: sDetail + }); + + var stack = this._stack; + var maxStackEntries = this.maxStackEntries; + if(maxStackEntries && !isNaN(maxStackEntries) && + (stack.length >= maxStackEntries)) { + stack.shift(); + } + stack.push(logEntry); + this.newLogEvent.fire(logEntry); + + if(this._browserConsoleEnabled) { + this._printToBrowserConsole(logEntry); + } + return true; + } + else { + return false; + } + }; + + /** + * Resets internal stack and startTime, enables Logger, and fires logResetEvent. + * + * @method reset + */ + YAHOO.widget.Logger.reset = function() { + this._stack = []; + this._startTime = new Date().getTime(); + this.loggerEnabled = true; + this.log("Logger reset"); + this.logResetEvent.fire(); + }; + + /** + * Public accessor to internal stack of log message objects. + * + * @method getStack + * @return {Object[]} Array of log message objects. + */ + YAHOO.widget.Logger.getStack = function() { + return this._stack; + }; + + /** + * Public accessor to internal start time. + * + * @method getStartTime + * @return {Date} Internal date of when Logger singleton was initialized. + */ + YAHOO.widget.Logger.getStartTime = function() { + return this._startTime; + }; + + /** + * Disables output to the browser's global console.log() function, which is used + * by the Firebug extension to Firefox as well as Safari. + * + * @method disableBrowserConsole + */ + YAHOO.widget.Logger.disableBrowserConsole = function() { + YAHOO.log("Logger output to the function console.log() has been disabled."); + this._browserConsoleEnabled = false; + }; + + /** + * Enables output to the browser's global console.log() function, which is used + * by the Firebug extension to Firefox as well as Safari. + * + * @method enableBrowserConsole + */ + YAHOO.widget.Logger.enableBrowserConsole = function() { + this._browserConsoleEnabled = true; + YAHOO.log("Logger output to the function console.log() has been enabled."); + }; + + /** + * Surpresses native JavaScript errors and outputs to console. By default, + * Logger does not handle JavaScript window error events. + * NB: Not all browsers support the window.onerror event. + * + * @method handleWindowErrors + */ + YAHOO.widget.Logger.handleWindowErrors = function() { + if(!YAHOO.widget.Logger._windowErrorsHandled) { + // Save any previously defined handler to call + if(window.error) { + YAHOO.widget.Logger._origOnWindowError = window.onerror; + } + window.onerror = YAHOO.widget.Logger._onWindowError; + YAHOO.widget.Logger._windowErrorsHandled = true; + YAHOO.log("Logger handling of window.onerror has been enabled."); + } + else { + YAHOO.log("Logger handling of window.onerror had already been enabled."); + } + }; + + /** + * Unsurpresses native JavaScript errors. By default, + * Logger does not handle JavaScript window error events. + * NB: Not all browsers support the window.onerror event. + * + * @method unhandleWindowErrors + */ + YAHOO.widget.Logger.unhandleWindowErrors = function() { + if(YAHOO.widget.Logger._windowErrorsHandled) { + // Revert to any previously defined handler to call + if(YAHOO.widget.Logger._origOnWindowError) { + window.onerror = YAHOO.widget.Logger._origOnWindowError; + YAHOO.widget.Logger._origOnWindowError = null; + } + else { + window.onerror = null; + } + YAHOO.widget.Logger._windowErrorsHandled = false; + YAHOO.log("Logger handling of window.onerror has been disabled."); + } + else { + YAHOO.log("Logger handling of window.onerror had already been disabled."); + } + }; + + ///////////////////////////////////////////////////////////////////////////// + // + // Public events + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Fired when a new category has been created. + * + * @event categoryCreateEvent + * @param sCategory {String} Category name. + */ + YAHOO.widget.Logger.categoryCreateEvent = + new YAHOO.util.CustomEvent("categoryCreate", this, true); + + /** + * Fired when a new source has been named. + * + * @event sourceCreateEvent + * @param sSource {String} Source name. + */ + YAHOO.widget.Logger.sourceCreateEvent = + new YAHOO.util.CustomEvent("sourceCreate", this, true); + + /** + * Fired when a new log message has been created. + * + * @event newLogEvent + * @param sMsg {String} Log message. + */ + YAHOO.widget.Logger.newLogEvent = new YAHOO.util.CustomEvent("newLog", this, true); + + /** + * Fired when the Logger has been reset has been created. + * + * @event logResetEvent + */ + YAHOO.widget.Logger.logResetEvent = new YAHOO.util.CustomEvent("logReset", this, true); + + ///////////////////////////////////////////////////////////////////////////// + // + // Private methods + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Creates a new category of log messages and fires categoryCreateEvent. + * + * @method _createNewCategory + * @param sCategory {String} Category name. + * @private + */ + YAHOO.widget.Logger._createNewCategory = function(sCategory) { + this.categories.push(sCategory); + this.categoryCreateEvent.fire(sCategory); + }; + + /** + * Checks to see if a category has already been created. + * + * @method _isNewCategory + * @param sCategory {String} Category name. + * @return {Boolean} Returns true if category is unknown, else returns false. + * @private + */ + YAHOO.widget.Logger._isNewCategory = function(sCategory) { + for(var i=0; i < this.categories.length; i++) { + if(sCategory == this.categories[i]) { + return false; + } + } + return true; + }; + + /** + * Creates a new source of log messages and fires sourceCreateEvent. + * + * @method _createNewSource + * @param sSource {String} Source name. + * @private + */ + YAHOO.widget.Logger._createNewSource = function(sSource) { + this.sources.push(sSource); + this.sourceCreateEvent.fire(sSource); + }; + + /** + * Checks to see if a source already exists. + * + * @method _isNewSource + * @param sSource {String} Source name. + * @return {Boolean} Returns true if source is unknown, else returns false. + * @private + */ + YAHOO.widget.Logger._isNewSource = function(sSource) { + if(sSource) { + for(var i=0; i < this.sources.length; i++) { + if(sSource == this.sources[i]) { + return false; + } + } + return true; + } + }; + + /** + * Outputs a log message to global console.log() function. + * + * @method _printToBrowserConsole + * @param oEntry {Object} Log entry object. + * @private + */ + YAHOO.widget.Logger._printToBrowserConsole = function(oEntry) { + if ((window.console && console.log) || + (window.opera && opera.postError)) { + var category = oEntry.category; + var label = oEntry.category.substring(0,4).toUpperCase(); + + var time = oEntry.time; + var localTime; + if (time.toLocaleTimeString) { + localTime = time.toLocaleTimeString(); + } + else { + localTime = time.toString(); + } + + var msecs = time.getTime(); + var elapsedTime = (YAHOO.widget.Logger._lastTime) ? + (msecs - YAHOO.widget.Logger._lastTime) : 0; + YAHOO.widget.Logger._lastTime = msecs; + + var output = + localTime + " (" + + elapsedTime + "ms): " + + oEntry.source + ": "; + + if (window.console) { + console.log(output, oEntry.msg); + } else { + opera.postError(output + oEntry.msg); + } + } + }; + + ///////////////////////////////////////////////////////////////////////////// + // + // Private event handlers + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Handles logging of messages due to window error events. + * + * @method _onWindowError + * @param sMsg {String} The error message. + * @param sUrl {String} URL of the error. + * @param sLine {String} Line number of the error. + * @private + */ + YAHOO.widget.Logger._onWindowError = function(sMsg,sUrl,sLine) { + // Logger is not in scope of this event handler + try { + YAHOO.widget.Logger.log(sMsg+' ('+sUrl+', line '+sLine+')', "window"); + if(YAHOO.widget.Logger._origOnWindowError) { + YAHOO.widget.Logger._origOnWindowError(); + } + } + catch(e) { + return false; + } + }; + + ///////////////////////////////////////////////////////////////////////////// + // + // First log + // + ///////////////////////////////////////////////////////////////////////////// + + YAHOO.widget.Logger.log("Logger initialized"); +} + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +(function () { +var Logger = YAHOO.widget.Logger, + u = YAHOO.util, + Dom = u.Dom, + Event = u.Event, + d = document; + +function make(el,props) { + el = d.createElement(el); + if (props) { + for (var p in props) { + if (props.hasOwnProperty(p)) { + el[p] = props[p]; + } + } + } + return el; +} + +/** + * The LogReader class provides UI to read messages logged to YAHOO.widget.Logger. + * + * @class LogReader + * @constructor + * @param elContainer {HTMLElement} (optional) DOM element reference of an existing DIV. + * @param elContainer {String} (optional) String ID of an existing DIV. + * @param oConfigs {Object} (optional) Object literal of configuration params. + */ +function LogReader(elContainer, oConfigs) { + this._sName = LogReader._index; + LogReader._index++; + + this._init.apply(this,arguments); + + /** + * Render the LogReader immediately upon instantiation. If set to false, + * you must call myLogReader.render() to generate the UI. + * + * @property autoRender + * @type {Boolean} + * @default true + */ + if (this.autoRender !== false) { + this.render(); + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// Static member variables +// +///////////////////////////////////////////////////////////////////////////// +YAHOO.lang.augmentObject(LogReader, { + /** + * Internal class member to index multiple LogReader instances. + * + * @property _memberName + * @static + * @type Number + * @default 0 + * @private + */ + _index : 0, + + /** + * Node template for the log entries + * @property ENTRY_TEMPLATE + * @static + * @type {HTMLElement} + * @default pre element with class yui-log-entry + */ + ENTRY_TEMPLATE : (function () { + return make('pre',{ className: 'yui-log-entry' }); + })(), + + /** + * Template used for innerHTML of verbose entry output. + * @property VERBOSE_TEMPLATE + * @static + * @default "<p><span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}:</p><p>{sourceAndDetail}</p><p>{message}</p>" + */ + VERBOSE_TEMPLATE : "

    {label} {totalTime}ms (+{elapsedTime}) {localTime}:

    {sourceAndDetail}

    {message}

    ", + + /** + * Template used for innerHTML of compact entry output. + * @property BASIC_TEMPLATE + * @static + * @default "<p><span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}</p>" + */ + BASIC_TEMPLATE : "

    {label} {totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}

    " +}); + +///////////////////////////////////////////////////////////////////////////// +// +// Public member variables +// +///////////////////////////////////////////////////////////////////////////// + +LogReader.prototype = { + /** + * Whether or not LogReader is enabled to output log messages. + * + * @property logReaderEnabled + * @type Boolean + * @default true + */ + logReaderEnabled : true, + + /** + * Public member to access CSS width of the LogReader container. + * + * @property width + * @type String + */ + width : null, + + /** + * Public member to access CSS height of the LogReader container. + * + * @property height + * @type String + */ + height : null, + + /** + * Public member to access CSS top position of the LogReader container. + * + * @property top + * @type String + */ + top : null, + + /** + * Public member to access CSS left position of the LogReader container. + * + * @property left + * @type String + */ + left : null, + + /** + * Public member to access CSS right position of the LogReader container. + * + * @property right + * @type String + */ + right : null, + + /** + * Public member to access CSS bottom position of the LogReader container. + * + * @property bottom + * @type String + */ + bottom : null, + + /** + * Public member to access CSS font size of the LogReader container. + * + * @property fontSize + * @type String + */ + fontSize : null, + + /** + * Whether or not the footer UI is enabled for the LogReader. + * + * @property footerEnabled + * @type Boolean + * @default true + */ + footerEnabled : true, + + /** + * Whether or not output is verbose (more readable). Setting to true will make + * output more compact (less readable). + * + * @property verboseOutput + * @type Boolean + * @default true + */ + verboseOutput : true, + + /** + * Custom output format for log messages. Defaults to null, which falls + * back to verboseOutput param deciding between LogReader.VERBOSE_TEMPLATE + * and LogReader.BASIC_TEMPLATE. Use bracketed place holders to mark where + * message info should go. Available place holder names include: + *
      + *
    • category
    • + *
    • label
    • + *
    • sourceAndDetail
    • + *
    • message
    • + *
    • localTime
    • + *
    • elapsedTime
    • + *
    • totalTime
    • + *
    + * + * @property entryFormat + * @type String + * @default null + */ + entryFormat : null, + + /** + * Whether or not newest message is printed on top. + * + * @property newestOnTop + * @type Boolean + */ + newestOnTop : true, + + /** + * Output timeout buffer in milliseconds. + * + * @property outputBuffer + * @type Number + * @default 100 + */ + outputBuffer : 100, + + /** + * Maximum number of messages a LogReader console will display. + * + * @property thresholdMax + * @type Number + * @default 500 + */ + thresholdMax : 500, + + /** + * When a LogReader console reaches its thresholdMax, it will clear out messages + * and print out the latest thresholdMin number of messages. + * + * @property thresholdMin + * @type Number + * @default 100 + */ + thresholdMin : 100, + + /** + * True when LogReader is in a collapsed state, false otherwise. + * + * @property isCollapsed + * @type Boolean + * @default false + */ + isCollapsed : false, + + /** + * True when LogReader is in a paused state, false otherwise. + * + * @property isPaused + * @type Boolean + * @default false + */ + isPaused : false, + + /** + * Enables draggable LogReader if DragDrop Utility is present. + * + * @property draggable + * @type Boolean + * @default true + */ + draggable : true, + + ///////////////////////////////////////////////////////////////////////////// + // + // Public methods + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Public accessor to the unique name of the LogReader instance. + * + * @method toString + * @return {String} Unique name of the LogReader instance. + */ + toString : function() { + return "LogReader instance" + this._sName; + }, + /** + * Pauses output of log messages. While paused, log messages are not lost, but + * get saved to a buffer and then output upon resume of LogReader. + * + * @method pause + */ + pause : function() { + this.isPaused = true; + this._timeout = null; + this.logReaderEnabled = false; + if (this._btnPause) { + this._btnPause.value = "Resume"; + } + }, + + /** + * Resumes output of log messages, including outputting any log messages that + * have been saved to buffer while paused. + * + * @method resume + */ + resume : function() { + this.isPaused = false; + this.logReaderEnabled = true; + this._printBuffer(); + if (this._btnPause) { + this._btnPause.value = "Pause"; + } + }, + + /** + * Adds the UI to the DOM, attaches event listeners, and bootstraps initial + * UI state. + * + * @method render + */ + render : function () { + if (this.rendered) { + return; + } + + this._initContainerEl(); + + this._initHeaderEl(); + this._initConsoleEl(); + this._initFooterEl(); + + this._initCategories(); + this._initSources(); + + this._initDragDrop(); + + // Subscribe to Logger custom events + Logger.newLogEvent.subscribe(this._onNewLog, this); + Logger.logResetEvent.subscribe(this._onReset, this); + + Logger.categoryCreateEvent.subscribe(this._onCategoryCreate, this); + Logger.sourceCreateEvent.subscribe(this._onSourceCreate, this); + + this.rendered = true; + + this._filterLogs(); + }, + + /** + * Removes the UI from the DOM entirely and detaches all event listeners. + * Implementers should note that Logger will still accumulate messages. + * + * @method destroy + */ + destroy : function () { + Event.purgeElement(this._elContainer,true); + this._elContainer.innerHTML = ''; + this._elContainer.parentNode.removeChild(this._elContainer); + + this.rendered = false; + }, + + /** + * Hides UI of LogReader. Logging functionality is not disrupted. + * + * @method hide + */ + hide : function() { + this._elContainer.style.display = "none"; + }, + + /** + * Shows UI of LogReader. Logging functionality is not disrupted. + * + * @method show + */ + show : function() { + this._elContainer.style.display = "block"; + }, + + /** + * Collapses UI of LogReader. Logging functionality is not disrupted. + * + * @method collapse + */ + collapse : function() { + this._elConsole.style.display = "none"; + if(this._elFt) { + this._elFt.style.display = "none"; + } + this._btnCollapse.value = "Expand"; + this.isCollapsed = true; + }, + + /** + * Expands UI of LogReader. Logging functionality is not disrupted. + * + * @method expand + */ + expand : function() { + this._elConsole.style.display = "block"; + if(this._elFt) { + this._elFt.style.display = "block"; + } + this._btnCollapse.value = "Collapse"; + this.isCollapsed = false; + }, + + /** + * Returns related checkbox element for given filter (i.e., category or source). + * + * @method getCheckbox + * @param {String} Category or source name. + * @return {Array} Array of all filter checkboxes. + */ + getCheckbox : function(filter) { + return this._filterCheckboxes[filter]; + }, + + /** + * Returns array of enabled categories. + * + * @method getCategories + * @return {String[]} Array of enabled categories. + */ + getCategories : function() { + return this._categoryFilters; + }, + + /** + * Shows log messages associated with given category. + * + * @method showCategory + * @param {String} Category name. + */ + showCategory : function(sCategory) { + var filtersArray = this._categoryFilters; + // Don't do anything if category is already enabled + // Use Array.indexOf if available... + if(filtersArray.indexOf) { + if(filtersArray.indexOf(sCategory) > -1) { + return; + } + } + // ...or do it the old-fashioned way + else { + for(var i=0; i -1) { + return; + } + } + // ...or do it the old-fashioned way + else { + for(var i=0; i", and "&" to HTML entities. + * + * @method html2Text + * @param sHtml {String} String to convert. + * @private + */ + html2Text : function(sHtml) { + if(sHtml) { + sHtml += ""; + return sHtml.replace(/&/g, "&"). + replace(//g, ">"); + } + return ""; + }, + +///////////////////////////////////////////////////////////////////////////// +// +// Private member variables +// +///////////////////////////////////////////////////////////////////////////// + + /** + * Name of LogReader instance. + * + * @property _sName + * @type String + * @private + */ + _sName : null, + + //TODO: remove + /** + * A class member shared by all LogReaders if a container needs to be + * created during instantiation. Will be null if a container element never needs to + * be created on the fly, such as when the implementer passes in their own element. + * + * @property _elDefaultContainer + * @type HTMLElement + * @private + */ + //YAHOO.widget.LogReader._elDefaultContainer = null; + + /** + * Buffer of log message objects for batch output. + * + * @property _buffer + * @type Object[] + * @private + */ + _buffer : null, + + /** + * Number of log messages output to console. + * + * @property _consoleMsgCount + * @type Number + * @default 0 + * @private + */ + _consoleMsgCount : 0, + + /** + * Date of last output log message. + * + * @property _lastTime + * @type Date + * @private + */ + _lastTime : null, + + /** + * Batched output timeout ID. + * + * @property _timeout + * @type Number + * @private + */ + _timeout : null, + + /** + * Hash of filters and their related checkbox elements. + * + * @property _filterCheckboxes + * @type Object + * @private + */ + _filterCheckboxes : null, + + /** + * Array of filters for log message categories. + * + * @property _categoryFilters + * @type String[] + * @private + */ + _categoryFilters : null, + + /** + * Array of filters for log message sources. + * + * @property _sourceFilters + * @type String[] + * @private + */ + _sourceFilters : null, + + /** + * LogReader container element. + * + * @property _elContainer + * @type HTMLElement + * @private + */ + _elContainer : null, + + /** + * LogReader header element. + * + * @property _elHd + * @type HTMLElement + * @private + */ + _elHd : null, + + /** + * LogReader collapse element. + * + * @property _elCollapse + * @type HTMLElement + * @private + */ + _elCollapse : null, + + /** + * LogReader collapse button element. + * + * @property _btnCollapse + * @type HTMLElement + * @private + */ + _btnCollapse : null, + + /** + * LogReader title header element. + * + * @property _title + * @type HTMLElement + * @private + */ + _title : null, + + /** + * LogReader console element. + * + * @property _elConsole + * @type HTMLElement + * @private + */ + _elConsole : null, + + /** + * LogReader footer element. + * + * @property _elFt + * @type HTMLElement + * @private + */ + _elFt : null, + + /** + * LogReader buttons container element. + * + * @property _elBtns + * @type HTMLElement + * @private + */ + _elBtns : null, + + /** + * Container element for LogReader category filter checkboxes. + * + * @property _elCategoryFilters + * @type HTMLElement + * @private + */ + _elCategoryFilters : null, + + /** + * Container element for LogReader source filter checkboxes. + * + * @property _elSourceFilters + * @type HTMLElement + * @private + */ + _elSourceFilters : null, + + /** + * LogReader pause button element. + * + * @property _btnPause + * @type HTMLElement + * @private + */ + _btnPause : null, + + /** + * Clear button element. + * + * @property _btnClear + * @type HTMLElement + * @private + */ + _btnClear : null, + + ///////////////////////////////////////////////////////////////////////////// + // + // Private methods + // + ///////////////////////////////////////////////////////////////////////////// + + /** + * Initializes the instance's message buffer, start time, etc + * + * @method _init + * @param container {String|HTMLElement} (optional) the render target + * @param config {Object} (optional) instance configuration + * @protected + */ + _init : function (container, config) { + // Internal vars + this._buffer = []; // output buffer + this._filterCheckboxes = {}; // pointers to checkboxes + this._lastTime = Logger.getStartTime(); // timestamp of last log message to console + + // Parse config vars here + if (config && (config.constructor == Object)) { + for(var param in config) { + if (config.hasOwnProperty(param)) { + this[param] = config[param]; + } + } + } + + this._elContainer = Dom.get(container); + + YAHOO.log("LogReader initialized", null, this.toString()); + }, + + /** + * Initializes the primary container element. + * + * @method _initContainerEl + * @private + */ + _initContainerEl : function() { + + // Default the container if unset or not a div + if(!this._elContainer || !/div$/i.test(this._elContainer.tagName)) { + this._elContainer = d.body.insertBefore(make("div"),d.body.firstChild); + // Only position absolutely if an in-DOM element is not supplied + Dom.addClass(this._elContainer,"yui-log-container"); + } + + Dom.addClass(this._elContainer,"yui-log"); + + // If implementer has provided container values, trust and set those + var style = this._elContainer.style, + styleProps = ['width','right','top','fontSize'], + prop,i; + + for (i = styleProps.length - 1; i >= 0; --i) { + prop = styleProps[i]; + if (this[prop]){ + style[prop] = this[prop]; + } + } + + if(this.left) { + style.left = this.left; + style.right = "auto"; + } + if(this.bottom) { + style.bottom = this.bottom; + style.top = "auto"; + } + + // Opera needs a little prodding to reflow sometimes + if (YAHOO.env.ua.opera) { + d.body.style += ''; + } + + }, + + /** + * Initializes the header element. + * + * @method _initHeaderEl + * @private + */ + _initHeaderEl : function() { + // Destroy header if present + if(this._elHd) { + // Unhook DOM events + Event.purgeElement(this._elHd, true); + + // Remove DOM elements + this._elHd.innerHTML = ""; + } + + // Create header + // TODO: refactor this into an innerHTML + this._elHd = make("div",{ + className: "yui-log-hd" + }); + Dom.generateId(this._elHd, 'yui-log-hd' + this._sName); + + this._elCollapse = make("div",{ className: 'yui-log-btns' }); + + this._btnCollapse = make("input",{ + type: 'button', + className: 'yui-log-button', + value: 'Collapse' + }); + Event.on(this._btnCollapse,'click',this._onClickCollapseBtn,this); + + + this._title = make("h4",{ innerHTML : "Logger Console" }); + + this._elCollapse.appendChild(this._btnCollapse); + this._elHd.appendChild(this._elCollapse); + this._elHd.appendChild(this._title); + this._elContainer.appendChild(this._elHd); + }, + + /** + * Initializes the console element. + * + * @method _initConsoleEl + * @private + */ + _initConsoleEl : function() { + // Destroy console + if(this._elConsole) { + // Unhook DOM events + Event.purgeElement(this._elConsole, true); + + // Remove DOM elements + this._elConsole.innerHTML = ""; + } + + // Ceate console + this._elConsole = make("div", { className: "yui-log-bd" }); + + // If implementer has provided console, trust and set those + if(this.height) { + this._elConsole.style.height = this.height; + } + + this._elContainer.appendChild(this._elConsole); + }, + + /** + * Initializes the footer element. + * + * @method _initFooterEl + * @private + */ + _initFooterEl : function() { + // Don't create footer elements if footer is disabled + if(this.footerEnabled) { + // Destroy console + if(this._elFt) { + // Unhook DOM events + Event.purgeElement(this._elFt, true); + + // Remove DOM elements + this._elFt.innerHTML = ""; + } + + // TODO: use innerHTML + this._elFt = make("div",{ className: "yui-log-ft" }); + this._elBtns = make("div", { className: "yui-log-btns" }); + this._btnPause = make("input", { + type: "button", + className: "yui-log-button", + value: "Pause" + }); + + Event.on(this._btnPause,'click',this._onClickPauseBtn,this); + + this._btnClear = make("input", { + type: "button", + className: "yui-log-button", + value: "Clear" + }); + + Event.on(this._btnClear,'click',this._onClickClearBtn,this); + + this._elCategoryFilters = make("div", { className: "yui-log-categoryfilters" }); + this._elSourceFilters = make("div", { className: "yui-log-sourcefilters" }); + + this._elBtns.appendChild(this._btnPause); + this._elBtns.appendChild(this._btnClear); + this._elFt.appendChild(this._elBtns); + this._elFt.appendChild(this._elCategoryFilters); + this._elFt.appendChild(this._elSourceFilters); + this._elContainer.appendChild(this._elFt); + } + }, + + /** + * Initializes Drag and Drop on the header element. + * + * @method _initDragDrop + * @private + */ + _initDragDrop : function() { + // If Drag and Drop utility is available... + // ...and draggable is true... + // ...then make the header draggable + if(u.DD && this.draggable && this._elHd) { + var ylog_dd = new u.DD(this._elContainer); + ylog_dd.setHandleElId(this._elHd.id); + //TODO: use class name + this._elHd.style.cursor = "move"; + } + }, + + /** + * Initializes category filters. + * + * @method _initCategories + * @private + */ + _initCategories : function() { + // Initialize category filters + this._categoryFilters = []; + var aInitialCategories = Logger.categories; + + for(var j=0; j < aInitialCategories.length; j++) { + var sCategory = aInitialCategories[j]; + + // Add category to the internal array of filters + this._categoryFilters.push(sCategory); + + // Add checkbox element if UI is enabled + if(this._elCategoryFilters) { + this._createCategoryCheckbox(sCategory); + } + } + }, + + /** + * Initializes source filters. + * + * @method _initSources + * @private + */ + _initSources : function() { + // Initialize source filters + this._sourceFilters = []; + var aInitialSources = Logger.sources; + + for(var j=0; j < aInitialSources.length; j++) { + var sSource = aInitialSources[j]; + + // Add source to the internal array of filters + this._sourceFilters.push(sSource); + + // Add checkbox element if UI is enabled + if(this._elSourceFilters) { + this._createSourceCheckbox(sSource); + } + } + }, + + /** + * Creates the UI for a category filter in the LogReader footer element. + * + * @method _createCategoryCheckbox + * @param sCategory {String} Category name. + * @private + */ + _createCategoryCheckbox : function(sCategory) { + if(this._elFt) { + var filter = make("span",{ className: "yui-log-filtergrp" }), + checkid = Dom.generateId(null, "yui-log-filter-" + sCategory + this._sName), + check = make("input", { + id: checkid, + className: "yui-log-filter-" + sCategory, + type: "checkbox", + category: sCategory + }), + label = make("label", { + htmlFor: checkid, + className: sCategory, + innerHTML: sCategory + }); + + + // Subscribe to the click event + Event.on(check,'click',this._onCheckCategory,this); + + this._filterCheckboxes[sCategory] = check; + + // Append el at the end so IE 5.5 can set "type" attribute + // and THEN set checked property + filter.appendChild(check); + filter.appendChild(label); + this._elCategoryFilters.appendChild(filter); + check.checked = true; + } + }, + + /** + * Creates a checkbox in the LogReader footer element to filter by source. + * + * @method _createSourceCheckbox + * @param sSource {String} Source name. + * @private + */ + _createSourceCheckbox : function(sSource) { + if(this._elFt) { + var filter = make("span",{ className: "yui-log-filtergrp" }), + checkid = Dom.generateId(null, "yui-log-filter-" + sSource + this._sName), + check = make("input", { + id: checkid, + className: "yui-log-filter-" + sSource, + type: "checkbox", + source: sSource + }), + label = make("label", { + htmlFor: checkid, + className: sSource, + innerHTML: sSource + }); + + + // Subscribe to the click event + Event.on(check,'click',this._onCheckSource,this); + + this._filterCheckboxes[sSource] = check; + + // Append el at the end so IE 5.5 can set "type" attribute + // and THEN set checked property + filter.appendChild(check); + filter.appendChild(label); + this._elSourceFilters.appendChild(filter); + check.checked = true; + } + }, + + /** + * Reprints all log messages in the stack through filters. + * + * @method _filterLogs + * @private + */ + _filterLogs : function() { + // Reprint stack with new filters + if (this._elConsole !== null) { + this.clearConsole(); + this._printToConsole(Logger.getStack()); + } + }, + + /** + * Sends buffer of log messages to output and clears buffer. + * + * @method _printBuffer + * @private + */ + _printBuffer : function() { + this._timeout = null; + + if(this._elConsole !== null) { + var thresholdMax = this.thresholdMax; + thresholdMax = (thresholdMax && !isNaN(thresholdMax)) ? thresholdMax : 500; + if(this._consoleMsgCount < thresholdMax) { + var entries = []; + for (var i=0; i this.thresholdMax)) { + thresholdMin = 0; + } + entriesStartIndex = (entriesLen > thresholdMin) ? (entriesLen - thresholdMin) : 0; + + // Iterate through all log entries + for(i=entriesStartIndex; ivar sheet = YAHOO.util.StyleSheet(..); + * or + *
    var sheet = new YAHOO.util.StyleSheet(..);
    + * + * The first parameter passed can be any of the following things: + *
      + *
    • The desired string name to register a new empty sheet
    • + *
    • The string name of an existing YAHOO.util.StyleSheet instance
    • + *
    • The unique yuiSSID generated for an existing YAHOO.util.StyleSheet instance
    • + *
    • The id of an existing <link> or <style> node
    • + *
    • The node reference for an existing <link> or <style> node
    • + *
    • A chunk of css text to create a new stylesheet from
    • + *
    + * + *

    If a string is passed, StyleSheet will first look in its static name + * registry for an existing sheet, then in the DOM for an element with that id. + * If neither are found and the string contains the { character, it will be + * used as a the initial cssText for a new StyleSheet. Otherwise, a new empty + * StyleSheet is created, assigned the string value as a name, and registered + * statically by that name.

    + * + *

    The optional second parameter is a string name to register the sheet as. + * This param is largely useful when providing a node id/ref or chunk of css + * text to create a populated instance.

    + * + * @class StyleSheet + * @constructor + * @param seed {String|<style> element} a style or link node, its id, or a name or + * yuiSSID of a StyleSheet, or a string of css text (see above) + * @param name {String} OPTIONAL name to register instance for future static + * access + */ +function StyleSheet(seed, name) { + var head, + node, + sheet, + cssRules = {}, + _rules, + _insertRule, + _deleteRule, + i,r,sel; + + // Factory or constructor + if (!(this instanceof StyleSheet)) { + return new StyleSheet(seed,name); + } + + // capture the DOM node if the string is an id + node = seed && (seed.nodeName ? seed : d.getElementById(seed)); + + // Check for the StyleSheet in the static registry + if (seed && sheets[seed]) { + return sheets[seed]; + } else if (node && node.yuiSSID && sheets[node.yuiSSID]) { + return sheets[node.yuiSSID]; + } + + // Create a style node if necessary + if (!node || !/^(?:style|link)$/i.test(node.nodeName)) { + node = d.createElement('style'); + node.type = 'text/css'; + } + + if (lang.isString(seed)) { + // Create entire sheet from seed cssText + if (seed.indexOf('{') != -1) { + // Not a load-time fork because low run-time impact and IE fails + // test for s.styleSheet at page load time (oddly) + if (node.styleSheet) { + node.styleSheet.cssText = seed; + } else { + node.appendChild(d.createTextNode(seed)); + } + } else if (!name) { + name = seed; + } + } + + if (!node.parentNode || node.parentNode.nodeName.toLowerCase() !== 'head') { + head = (node.ownerDocument || d).getElementsByTagName('head')[0]; + // styleSheet isn't available on the style node in FF2 until appended + // to the head element. style nodes appended to body do not affect + // change in Safari. + head.appendChild(node); + } + + // Begin setting up private aliases to the important moving parts + // 1. The stylesheet object + // IE stores StyleSheet under the "styleSheet" property + // Safari doesn't populate sheet for xdomain link elements + sheet = node.sheet || node.styleSheet; + + // 2. The style rules collection + // IE stores the rules collection under the "rules" property + _rules = sheet && ('cssRules' in sheet) ? 'cssRules' : 'rules'; + + // 3. The method to remove a rule from the stylesheet + // IE supports removeRule + _deleteRule = ('deleteRule' in sheet) ? + function (i) { sheet.deleteRule(i); } : + function (i) { sheet.removeRule(i); }; + + // 4. The method to add a new rule to the stylesheet + // IE supports addRule with different signature + _insertRule = ('insertRule' in sheet) ? + function (sel,css,i) { sheet.insertRule(sel+' {'+css+'}',i); } : + function (sel,css,i) { sheet.addRule(sel,css,i); }; + + // 5. Initialize the cssRules map from the node + // xdomain link nodes forbid access to the cssRules collection, so this + // will throw an error. + // TODO: research alternate stylesheet, @media + for (i = sheet[_rules].length - 1; i >= 0; --i) { + r = sheet[_rules][i]; + sel = r.selectorText; + + if (cssRules[sel]) { + cssRules[sel].style.cssText += ';' + r.style.cssText; + _deleteRule(i); + } else { + cssRules[sel] = r; + } + } + + // Cache the instance by the generated Id + node.yuiSSID = 'yui-stylesheet-' + (ssId++); + StyleSheet.register(node.yuiSSID,this); + + // Register the instance by name if provided or defaulted from seed + if (name) { + StyleSheet.register(name,this); + } + + // Public API + lang.augmentObject(this,{ + /** + * Get the unique yuiSSID for this StyleSheet instance + * + * @method getId + * @return {Number} the static id + */ + getId : function () { return node.yuiSSID; }, + + /** + * The <style> element that this instance encapsulates + * + * @property node + * @type HTMLElement + */ + node : node, + + /** + * Enable all the rules in the sheet + * + * @method enable + * @return {StyleSheet} the instance + * @chainable + */ + // Enabling/disabling the stylesheet. Changes may be made to rules + // while disabled. + enable : function () { sheet.disabled = false; return this; }, + + /** + * Disable all the rules in the sheet. Rules may be changed while the + * StyleSheet is disabled. + * + * @method disable + * @return {StyleSheet} the instance + * @chainable + */ + disable : function () { sheet.disabled = true; return this; }, + + /** + * Returns boolean indicating whether the StyleSheet is enabled + * + * @method isEnabled + * @return {Boolean} is it enabled? + */ + isEnabled : function () { return !sheet.disabled; }, + + /** + *

    Set style properties for a provided selector string. + * If the selector includes commas, it will be split into individual + * selectors and applied accordingly. If the selector string does not + * have a corresponding rule in the sheet, it will be added.

    + * + *

    The second parameter can be either a string of CSS text, + * formatted as CSS ("font-size: 10px;"), or an object collection of + * properties and their new values. Object properties must be in + * JavaScript format ({ fontSize: "10px" }).

    + * + *

    The float style property will be set by any of "float", + * "styleFloat", or "cssFloat" if passed in the + * object map. Use "float: left;" format when passing a CSS text + * string.

    + * + * @method set + * @param sel {String} the selector string to apply the changes to + * @param css {Object|String} Object literal of style properties and + * new values, or a string of cssText + * @return {StyleSheet} the StyleSheet instance + * @chainable + */ + set : function (sel,css) { + var rule = cssRules[sel], + multi = sel.split(/\s*,\s*/),i, + idx; + + // IE's addRule doesn't support multiple comma delimited selectors + if (multi.length > 1) { + for (i = multi.length - 1; i >= 0; --i) { + this.set(multi[i], css); + } + return this; + } + + // Some selector values can cause IE to hang + if (!StyleSheet.isValidSelector(sel)) { + YAHOO.log("Invalid selector '"+sel+"' passed to set (ignoring).",'warn','StyleSheet'); + return this; + } + + // Opera throws an error if there's a syntax error in assigned + // cssText. Avoid this using a worker style collection, then + // assigning the resulting cssText. + if (rule) { + rule.style.cssText = StyleSheet.toCssText(css,rule.style.cssText); + } else { + idx = sheet[_rules].length; + css = StyleSheet.toCssText(css); + + // IE throws an error when attempting to addRule(sel,'',n) + // which would crop up if no, or only invalid values are used + if (css) { + _insertRule(sel, css, idx); + + // Safari replaces the rules collection, but maintains the + // rule instances in the new collection when rules are + // added/removed + cssRules[sel] = sheet[_rules][idx]; + } + } + return this; + }, + + /** + *

    Unset style properties for a provided selector string, removing + * their effect from the style cascade.

    + * + *

    If the selector includes commas, it will be split into individual + * selectors and applied accordingly. If there are no properties + * remaining in the rule after unsetting, the rule is removed.

    + * + *

    The style property or properties in the second parameter must be the + *

    JavaScript style property names. E.g. fontSize rather than font-size.

    + * + *

    The float style property will be unset by any of "float", + * "styleFloat", or "cssFloat".

    + * + * @method unset + * @param sel {String} the selector string to apply the changes to + * @param css {String|Array} style property name or Array of names + * @return {StyleSheet} the StyleSheet instance + * @chainable + */ + unset : function (sel,css) { + var rule = cssRules[sel], + multi = sel.split(/\s*,\s*/), + remove = !css, + rules, i; + + // IE's addRule doesn't support multiple comma delimited selectors + // so rules are mapped internally by atomic selectors + if (multi.length > 1) { + for (i = multi.length - 1; i >= 0; --i) { + this.unset(multi[i], css); + } + return this; + } + + if (rule) { + if (!remove) { + if (!lang.isArray(css)) { + css = [css]; + } + + workerStyle.cssText = rule.style.cssText; + for (i = css.length - 1; i >= 0; --i) { + _unsetProperty(workerStyle,css[i]); + } + + if (workerStyle.cssText) { + rule.style.cssText = workerStyle.cssText; + } else { + remove = true; + } + } + + if (remove) { // remove the rule altogether + rules = sheet[_rules]; + for (i = rules.length - 1; i >= 0; --i) { + if (rules[i] === rule) { + delete cssRules[sel]; + _deleteRule(i); + break; + } + } + } + } + return this; + }, + + /** + * Get the current cssText for a rule or the entire sheet. If the + * selector param is supplied, only the cssText for that rule will be + * returned, if found. If the selector string targets multiple + * selectors separated by commas, the cssText of the first rule only + * will be returned. If no selector string, the stylesheet's full + * cssText will be returned. + * + * @method getCssText + * @param sel {String} Selector string + * @return {String} + */ + getCssText : function (sel) { + var rule, css, selector; + + if (lang.isString(sel)) { + // IE's addRule doesn't support multiple comma delimited + // selectors so rules are mapped internally by atomic selectors + rule = cssRules[sel.split(/\s*,\s*/)[0]]; + + return rule ? rule.style.cssText : null; + } else { + css = []; + for (selector in cssRules) { + if (cssRules.hasOwnProperty(selector)) { + rule = cssRules[selector]; + css.push(rule.selectorText+" {"+rule.style.cssText+"}"); + } + } + return css.join("\n"); + } + } + },true); + +} + +_toCssText = function (css,base) { + var f = css.styleFloat || css.cssFloat || css['float'], + prop; + + // A very difficult to repro/isolate IE 9 beta (and Platform Preview 7) bug + // was reduced to this line throwing the error: + // "Invalid this pointer used as target for method call" + // It appears that the style collection is corrupted. The error is + // catchable, so in a best effort to work around it, replace the + // p and workerStyle and try the assignment again. + try { + workerStyle.cssText = base || ''; + } catch (ex) { + YAHOO.log("Worker style collection corrupted. Replacing.", "warn", "StyleSheet"); + p = d.createElement('p'); + workerStyle = p.style; + workerStyle.cssText = base || ''; + } + + if (lang.isString(css)) { + // There is a danger here of incremental memory consumption in Opera + workerStyle.cssText += ';' + css; + } else { + if (f && !css[floatAttr]) { + css = lang.merge(css); + delete css.styleFloat; delete css.cssFloat; delete css['float']; + css[floatAttr] = f; + } + + for (prop in css) { + if (css.hasOwnProperty(prop)) { + try { + // IE throws Invalid Value errors and doesn't like whitespace + // in values ala ' red' or 'red ' + workerStyle[prop] = lang.trim(css[prop]); + } + catch (e) { + YAHOO.log('Error assigning property "'+prop+'" to "'+css[prop]+ + "\" (ignored):\n"+e.message,'warn','StyleSheet'); + } + } + } + } + + return workerStyle.cssText; +}; + +lang.augmentObject(StyleSheet, { + /** + *

    Converts an object literal of style properties and values into a string + * of css text. This can then be assigned to el.style.cssText.

    + * + *

    The optional second parameter is a cssText string representing the + * starting state of the style prior to alterations. This is most often + * extracted from the eventual target's current el.style.cssText.

    + * + * @method StyleSheet.toCssText + * @param css {Object} object literal of style properties and values + * @param cssText {String} OPTIONAL starting cssText value + * @return {String} the resulting cssText string + * @static + */ + toCssText : (('opacity' in workerStyle) ? _toCssText : + // Wrap IE's toCssText to catch opacity. The copy/merge is to preserve + // the input object's integrity, but if float and opacity are set, the + // input will be copied twice in IE. Is there a way to avoid this + // without increasing the byte count? + function (css, cssText) { + if (lang.isObject(css) && 'opacity' in css) { + css = lang.merge(css,{ + filter: 'alpha(opacity='+(css.opacity*100)+')' + }); + delete css.opacity; + } + return _toCssText(css,cssText); + }), + + /** + * Registers a StyleSheet instance in the static registry by the given name + * + * @method StyleSheet.register + * @param name {String} the name to assign the StyleSheet in the registry + * @param sheet {StyleSheet} The StyleSheet instance + * @return {Boolean} false if no name or sheet is not a StyleSheet + * instance. true otherwise. + * @static + */ + register : function (name,sheet) { + return !!(name && sheet instanceof StyleSheet && + !sheets[name] && (sheets[name] = sheet)); + }, + + /** + *

    Determines if a selector string is safe to use. Used internally + * in set to prevent IE from locking up when attempting to add a rule for a + * "bad selector".

    + * + *

    Bad selectors are considered to be any string containing unescaped + * `~!@$%^&()+=|{}[];'"?< or space. Also forbidden are . or # followed by + * anything other than an alphanumeric. Additionally -abc or .-abc or + * #_abc or '# ' all fail. There are likely more failure cases, so + * please file a bug if you encounter one.

    + * + * @method StyleSheet.isValidSelector + * @param sel {String} the selector string + * @return {Boolean} + * @static + */ + isValidSelector : function (sel) { + var valid = false; + + if (sel && lang.isString(sel)) { + + if (!selectors.hasOwnProperty(sel)) { + // TEST: there should be nothing but white-space left after + // these destructive regexs + selectors[sel] = !/\S/.test( + // combinators + sel.replace(/\s+|\s*[+~>]\s*/g,' '). + // attribute selectors (contents not validated) + replace(/([^ ])\[.*?\]/g,'$1'). + // pseudo-class|element selectors (contents of parens + // such as :nth-of-type(2) or :not(...) not validated) + replace(/([^ ])::?[a-z][a-z\-]+[a-z](?:\(.*?\))?/ig,'$1'). + // element tags + replace(/(?:^| )[a-z0-6]+/ig,' '). + // escaped characters + replace(/\\./g,''). + // class and id identifiers + replace(/[.#]\w[\w\-]*/g,'')); + } + + valid = selectors[sel]; + } + + return valid; + } +},true); + +YAHOO.util.StyleSheet = StyleSheet; + +})(); + +/* + +NOTES + * Style node must be added to the head element. Safari does not honor styles + applied to StyleSheet objects on style nodes in the body. + * StyleSheet object is created on the style node when the style node is added + to the head element in Firefox 2 (and maybe 3?) + * The cssRules collection is replaced after insertRule/deleteRule calls in + Safari 3.1. Existing Rules are used in the new collection, so the collection + cannot be cached, but the rules can be. + * Opera requires that the index be passed with insertRule. + * Same-domain restrictions prevent modifying StyleSheet objects attached to + link elements with remote href (or "about:blank" or "javascript:false") + * Same-domain restrictions prevent reading StyleSheet cssRules/rules + collection of link elements with remote href (or "about:blank" or + "javascript:false") + * Same-domain restrictions result in Safari not populating node.sheet property + for link elements with remote href (et.al) + * IE names StyleSheet related properties and methods differently (see code) + * IE converts tag names to upper case in the Rule's selectorText + * IE converts empty string assignment to complex properties to value settings + for all child properties. E.g. style.background = '' sets non-'' values on + style.backgroundPosition, style.backgroundColor, etc. All else clear + style.background and all child properties. + * IE assignment style.filter = '' will result in style.cssText == 'FILTER:' + * All browsers support Rule.style.cssText as a read/write property, leaving + only opacity needing to be accounted for. + * Benchmarks of style.property = value vs style.cssText += 'property: value' + indicate cssText is slightly slower for single property assignment. For + multiple property assignment, cssText speed stays relatively the same where + style.property speed decreases linearly by the number of properties set. + Exception being Opera 9.27, where style.property is always faster than + style.cssText. + * Opera 9.5b throws a syntax error when assigning cssText with a syntax error. + * Opera 9.5 doesn't honor rule.style.cssText = ''. Previous style persists. + You have to remove the rule altogether. + * Stylesheet properties set with !important will trump inline style set on an + element or in el.style.property. + * Creating a worker style collection like document.createElement('p').style; + will fail after a time in FF (~5secs of inactivity). Property assignments + will not alter the property or cssText. It may be the generated node is + garbage collected and the style collection becomes inert (speculation). + * IE locks up when attempting to add a rule with a selector including at least + characters {[]}~`!@%^&*()+=|? (unescaped) and leading _ or - + such as addRule('-foo','{ color: red }') or addRule('._abc','{...}') + * IE's addRule doesn't support comma separated selectors such as + addRule('.foo, .bar','{..}') + * IE throws an error on valid values with leading/trailing white space. + * When creating an entire sheet at once, only FF2/3 & Opera allow creating a + style node, setting its innerHTML and appending to head. + * When creating an entire sheet at once, Safari requires the style node to be + created with content in innerHTML of another element. + * When creating an entire sheet at once, IE requires the style node content to + be set via node.styleSheet.cssText + * When creating an entire sheet at once in IE, styleSheet.cssText can't be + written until node.type = 'text/css'; is performed. + * When creating an entire sheet at once in IE, load-time fork on + var styleNode = d.createElement('style'); _method = styleNode.styleSheet ?.. + fails (falsey). During run-time, the test for .styleSheet works fine + * Setting complex properties in cssText will SOMETIMES allow child properties + to be unset + set unset FF2 FF3 S3.1 IE6 IE7 Op9.27 Op9.5 + ---------- ----------------- --- --- ---- --- --- ------ ----- + border -top NO NO YES YES YES YES YES + -top-color NO NO YES YES YES + -color NO NO NO NO NO + background -color NO NO YES YES YES + -position NO NO YES YES YES + -position-x NO NO NO NO NO + font line-height YES YES NO NO NO NO YES + -style YES YES NO YES YES + -size YES YES NO YES YES + -size-adjust ??? ??? n/a n/a n/a ??? ??? + padding -top NO NO YES YES YES + margin -top NO NO YES YES YES + list-style -type YES YES YES YES YES + -position YES YES YES YES YES + overflow -x NO NO YES n/a YES + + ??? - unsetting font-size-adjust has the same effect as unsetting font-size + * FireFox and WebKit populate rule.cssText as "SELECTOR { CSSTEXT }", but + Opera and IE do not. + * IE6 and IE7 silently ignore the { and } if passed into addRule('.foo','{ + color:#000}',0). IE8 does not and creates an empty rule. + * IE6-8 addRule('.foo','',n) throws an error. Must supply *some* cssText +*/ + +YAHOO.register("stylesheet", YAHOO.util.StyleSheet, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet-min.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet-min.js new file mode 100644 index 0000000..fbb918d --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet-min.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +(function(){var j=document,b=j.createElement("p"),e=b.style,c=YAHOO.lang,m={},i={},f=0,k=("cssFloat" in e)?"cssFloat":"styleFloat",g,a,l;a=("opacity" in e)?function(d){d.opacity="";}:function(d){d.filter="";};e.border="1px solid red";e.border="";l=e.borderLeft?function(d,o){var n;if(o!==k&&o.toLowerCase().indexOf("float")!=-1){o=k;}if(typeof d[o]==="string"){switch(o){case"opacity":case"filter":a(d);break;case"font":d.font=d.fontStyle=d.fontVariant=d.fontWeight=d.fontSize=d.lineHeight=d.fontFamily="";break;default:for(n in d){if(n.indexOf(o)===0){d[n]="";}}}}}:function(d,n){if(n!==k&&n.toLowerCase().indexOf("float")!=-1){n=k;}if(c.isString(d[n])){if(n==="opacity"){a(d);}else{d[n]="";}}};function h(u,o){var x,s,w,v={},n,y,q,t,d,p;if(!(this instanceof h)){return new h(u,o);}s=u&&(u.nodeName?u:j.getElementById(u));if(u&&i[u]){return i[u];}else{if(s&&s.yuiSSID&&i[s.yuiSSID]){return i[s.yuiSSID];}}if(!s||!/^(?:style|link)$/i.test(s.nodeName)){s=j.createElement("style");s.type="text/css";}if(c.isString(u)){if(u.indexOf("{")!=-1){if(s.styleSheet){s.styleSheet.cssText=u;}else{s.appendChild(j.createTextNode(u));}}else{if(!o){o=u;}}}if(!s.parentNode||s.parentNode.nodeName.toLowerCase()!=="head"){x=(s.ownerDocument||j).getElementsByTagName("head")[0];x.appendChild(s);}w=s.sheet||s.styleSheet;n=w&&("cssRules" in w)?"cssRules":"rules";q=("deleteRule" in w)?function(r){w.deleteRule(r);}:function(r){w.removeRule(r);};y=("insertRule" in w)?function(A,z,r){w.insertRule(A+" {"+z+"}",r);}:function(A,z,r){w.addRule(A,z,r);};for(t=w[n].length-1;t>=0;--t){d=w[n][t];p=d.selectorText;if(v[p]){v[p].style.cssText+=";"+d.style.cssText;q(t);}else{v[p]=d;}}s.yuiSSID="yui-stylesheet-"+(f++);h.register(s.yuiSSID,this);if(o){h.register(o,this);}c.augmentObject(this,{getId:function(){return s.yuiSSID;},node:s,enable:function(){w.disabled=false;return this;},disable:function(){w.disabled=true;return this;},isEnabled:function(){return !w.disabled;},set:function(B,A){var D=v[B],C=B.split(/\s*,\s*/),z,r;if(C.length>1){for(z=C.length-1;z>=0;--z){this.set(C[z],A);}return this;}if(!h.isValidSelector(B)){return this;}if(D){D.style.cssText=h.toCssText(A,D.style.cssText);}else{r=w[n].length;A=h.toCssText(A);if(A){y(B,A,r);v[B]=w[n][r];}}return this;},unset:function(B,A){var D=v[B],C=B.split(/\s*,\s*/),r=!A,E,z;if(C.length>1){for(z=C.length-1;z>=0;--z){this.unset(C[z],A);}return this;}if(D){if(!r){if(!c.isArray(A)){A=[A];}e.cssText=D.style.cssText;for(z=A.length-1;z>=0;--z){l(e,A[z]);}if(e.cssText){D.style.cssText=e.cssText;}else{r=true;}}if(r){E=w[n];for(z=E.length-1;z>=0;--z){if(E[z]===D){delete v[B];q(z);break;}}}}return this;},getCssText:function(A){var B,z,r;if(c.isString(A)){B=v[A.split(/\s*,\s*/)[0]];return B?B.style.cssText:null;}else{z=[];for(r in v){if(v.hasOwnProperty(r)){B=v[r];z.push(B.selectorText+" {"+B.style.cssText+"}");}}return z.join("\n");}}},true);}g=function(n,p){var o=n.styleFloat||n.cssFloat||n["float"],r;try{e.cssText=p||"";}catch(d){b=j.createElement("p");e=b.style;e.cssText=p||"";}if(c.isString(n)){e.cssText+=";"+n;}else{if(o&&!n[k]){n=c.merge(n);delete n.styleFloat;delete n.cssFloat;delete n["float"];n[k]=o;}for(r in n){if(n.hasOwnProperty(r)){try{e[r]=c.trim(n[r]);}catch(q){}}}}return e.cssText;};c.augmentObject(h,{toCssText:(("opacity" in e)?g:function(d,n){if(c.isObject(d)&&"opacity" in d){d=c.merge(d,{filter:"alpha(opacity="+(d.opacity*100)+")"});delete d.opacity;}return g(d,n);}),register:function(d,n){return !!(d&&n instanceof h&&!i[d]&&(i[d]=n));},isValidSelector:function(n){var d=false;if(n&&c.isString(n)){if(!m.hasOwnProperty(n)){m[n]=!/\S/.test(n.replace(/\s+|\s*[+~>]\s*/g," ").replace(/([^ ])\[.*?\]/g,"$1").replace(/([^ ])::?[a-z][a-z\-]+[a-z](?:\(.*?\))?/ig,"$1").replace(/(?:^| )[a-z0-6]+/ig," ").replace(/\\./g,"").replace(/[.#]\w[\w\-]*/g,""));}d=m[n];}return d;}},true);YAHOO.util.StyleSheet=h;})();YAHOO.register("stylesheet",YAHOO.util.StyleSheet,{version:"2.9.0",build:"2800"}); \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet.js new file mode 100644 index 0000000..36ef6b8 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/stylesheet/stylesheet.js @@ -0,0 +1,656 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +/** + * The StyleSheet component is a utility for managing css rules at the + * stylesheet level + * + * @module stylesheet + * @namespace YAHOO.util + * @requires yahoo + */ +(function () { + +var d = document, + p = d.createElement('p'), // Have to hold the node (see notes) + workerStyle = p.style, // worker style collection + lang = YAHOO.lang, + selectors = {}, + sheets = {}, + ssId = 0, + floatAttr = ('cssFloat' in workerStyle) ? 'cssFloat' : 'styleFloat', + _toCssText, + _unsetOpacity, + _unsetProperty; + +/* + * Normalizes the removal of an assigned style for opacity. IE uses the filter property. + */ +_unsetOpacity = ('opacity' in workerStyle) ? + function (style) { style.opacity = ''; } : + function (style) { style.filter = ''; }; + +/* + * Normalizes the removal of an assigned style for a given property. Expands + * shortcut properties if necessary and handles the various names for the float property. + */ +workerStyle.border = "1px solid red"; +workerStyle.border = ''; // IE doesn't unset child properties +_unsetProperty = workerStyle.borderLeft ? + function (style,prop) { + var p; + if (prop !== floatAttr && prop.toLowerCase().indexOf('float') != -1) { + prop = floatAttr; + } + if (typeof style[prop] === 'string') { + switch (prop) { + case 'opacity': + case 'filter' : _unsetOpacity(style); break; + case 'font' : + style.font = style.fontStyle = style.fontVariant = + style.fontWeight = style.fontSize = style.lineHeight = + style.fontFamily = ''; + break; + default : + for (p in style) { + if (p.indexOf(prop) === 0) { + style[p] = ''; + } + } + } + } + } : + function (style,prop) { + if (prop !== floatAttr && prop.toLowerCase().indexOf('float') != -1) { + prop = floatAttr; + } + if (lang.isString(style[prop])) { + if (prop === 'opacity') { + _unsetOpacity(style); + } else { + style[prop] = ''; + } + } + }; + +/** + * Create an instance of YAHOO.util.StyleSheet to encapsulate a css stylesheet. + * The constructor can be called using function or constructor syntax. + *
    var sheet = YAHOO.util.StyleSheet(..);
    + * or + *
    var sheet = new YAHOO.util.StyleSheet(..);
    + * + * The first parameter passed can be any of the following things: + *
      + *
    • The desired string name to register a new empty sheet
    • + *
    • The string name of an existing YAHOO.util.StyleSheet instance
    • + *
    • The unique yuiSSID generated for an existing YAHOO.util.StyleSheet instance
    • + *
    • The id of an existing <link> or <style> node
    • + *
    • The node reference for an existing <link> or <style> node
    • + *
    • A chunk of css text to create a new stylesheet from
    • + *
    + * + *

    If a string is passed, StyleSheet will first look in its static name + * registry for an existing sheet, then in the DOM for an element with that id. + * If neither are found and the string contains the { character, it will be + * used as a the initial cssText for a new StyleSheet. Otherwise, a new empty + * StyleSheet is created, assigned the string value as a name, and registered + * statically by that name.

    + * + *

    The optional second parameter is a string name to register the sheet as. + * This param is largely useful when providing a node id/ref or chunk of css + * text to create a populated instance.

    + * + * @class StyleSheet + * @constructor + * @param seed {String|<style> element} a style or link node, its id, or a name or + * yuiSSID of a StyleSheet, or a string of css text (see above) + * @param name {String} OPTIONAL name to register instance for future static + * access + */ +function StyleSheet(seed, name) { + var head, + node, + sheet, + cssRules = {}, + _rules, + _insertRule, + _deleteRule, + i,r,sel; + + // Factory or constructor + if (!(this instanceof StyleSheet)) { + return new StyleSheet(seed,name); + } + + // capture the DOM node if the string is an id + node = seed && (seed.nodeName ? seed : d.getElementById(seed)); + + // Check for the StyleSheet in the static registry + if (seed && sheets[seed]) { + return sheets[seed]; + } else if (node && node.yuiSSID && sheets[node.yuiSSID]) { + return sheets[node.yuiSSID]; + } + + // Create a style node if necessary + if (!node || !/^(?:style|link)$/i.test(node.nodeName)) { + node = d.createElement('style'); + node.type = 'text/css'; + } + + if (lang.isString(seed)) { + // Create entire sheet from seed cssText + if (seed.indexOf('{') != -1) { + // Not a load-time fork because low run-time impact and IE fails + // test for s.styleSheet at page load time (oddly) + if (node.styleSheet) { + node.styleSheet.cssText = seed; + } else { + node.appendChild(d.createTextNode(seed)); + } + } else if (!name) { + name = seed; + } + } + + if (!node.parentNode || node.parentNode.nodeName.toLowerCase() !== 'head') { + head = (node.ownerDocument || d).getElementsByTagName('head')[0]; + // styleSheet isn't available on the style node in FF2 until appended + // to the head element. style nodes appended to body do not affect + // change in Safari. + head.appendChild(node); + } + + // Begin setting up private aliases to the important moving parts + // 1. The stylesheet object + // IE stores StyleSheet under the "styleSheet" property + // Safari doesn't populate sheet for xdomain link elements + sheet = node.sheet || node.styleSheet; + + // 2. The style rules collection + // IE stores the rules collection under the "rules" property + _rules = sheet && ('cssRules' in sheet) ? 'cssRules' : 'rules'; + + // 3. The method to remove a rule from the stylesheet + // IE supports removeRule + _deleteRule = ('deleteRule' in sheet) ? + function (i) { sheet.deleteRule(i); } : + function (i) { sheet.removeRule(i); }; + + // 4. The method to add a new rule to the stylesheet + // IE supports addRule with different signature + _insertRule = ('insertRule' in sheet) ? + function (sel,css,i) { sheet.insertRule(sel+' {'+css+'}',i); } : + function (sel,css,i) { sheet.addRule(sel,css,i); }; + + // 5. Initialize the cssRules map from the node + // xdomain link nodes forbid access to the cssRules collection, so this + // will throw an error. + // TODO: research alternate stylesheet, @media + for (i = sheet[_rules].length - 1; i >= 0; --i) { + r = sheet[_rules][i]; + sel = r.selectorText; + + if (cssRules[sel]) { + cssRules[sel].style.cssText += ';' + r.style.cssText; + _deleteRule(i); + } else { + cssRules[sel] = r; + } + } + + // Cache the instance by the generated Id + node.yuiSSID = 'yui-stylesheet-' + (ssId++); + StyleSheet.register(node.yuiSSID,this); + + // Register the instance by name if provided or defaulted from seed + if (name) { + StyleSheet.register(name,this); + } + + // Public API + lang.augmentObject(this,{ + /** + * Get the unique yuiSSID for this StyleSheet instance + * + * @method getId + * @return {Number} the static id + */ + getId : function () { return node.yuiSSID; }, + + /** + * The <style> element that this instance encapsulates + * + * @property node + * @type HTMLElement + */ + node : node, + + /** + * Enable all the rules in the sheet + * + * @method enable + * @return {StyleSheet} the instance + * @chainable + */ + // Enabling/disabling the stylesheet. Changes may be made to rules + // while disabled. + enable : function () { sheet.disabled = false; return this; }, + + /** + * Disable all the rules in the sheet. Rules may be changed while the + * StyleSheet is disabled. + * + * @method disable + * @return {StyleSheet} the instance + * @chainable + */ + disable : function () { sheet.disabled = true; return this; }, + + /** + * Returns boolean indicating whether the StyleSheet is enabled + * + * @method isEnabled + * @return {Boolean} is it enabled? + */ + isEnabled : function () { return !sheet.disabled; }, + + /** + *

    Set style properties for a provided selector string. + * If the selector includes commas, it will be split into individual + * selectors and applied accordingly. If the selector string does not + * have a corresponding rule in the sheet, it will be added.

    + * + *

    The second parameter can be either a string of CSS text, + * formatted as CSS ("font-size: 10px;"), or an object collection of + * properties and their new values. Object properties must be in + * JavaScript format ({ fontSize: "10px" }).

    + * + *

    The float style property will be set by any of "float", + * "styleFloat", or "cssFloat" if passed in the + * object map. Use "float: left;" format when passing a CSS text + * string.

    + * + * @method set + * @param sel {String} the selector string to apply the changes to + * @param css {Object|String} Object literal of style properties and + * new values, or a string of cssText + * @return {StyleSheet} the StyleSheet instance + * @chainable + */ + set : function (sel,css) { + var rule = cssRules[sel], + multi = sel.split(/\s*,\s*/),i, + idx; + + // IE's addRule doesn't support multiple comma delimited selectors + if (multi.length > 1) { + for (i = multi.length - 1; i >= 0; --i) { + this.set(multi[i], css); + } + return this; + } + + // Some selector values can cause IE to hang + if (!StyleSheet.isValidSelector(sel)) { + return this; + } + + // Opera throws an error if there's a syntax error in assigned + // cssText. Avoid this using a worker style collection, then + // assigning the resulting cssText. + if (rule) { + rule.style.cssText = StyleSheet.toCssText(css,rule.style.cssText); + } else { + idx = sheet[_rules].length; + css = StyleSheet.toCssText(css); + + // IE throws an error when attempting to addRule(sel,'',n) + // which would crop up if no, or only invalid values are used + if (css) { + _insertRule(sel, css, idx); + + // Safari replaces the rules collection, but maintains the + // rule instances in the new collection when rules are + // added/removed + cssRules[sel] = sheet[_rules][idx]; + } + } + return this; + }, + + /** + *

    Unset style properties for a provided selector string, removing + * their effect from the style cascade.

    + * + *

    If the selector includes commas, it will be split into individual + * selectors and applied accordingly. If there are no properties + * remaining in the rule after unsetting, the rule is removed.

    + * + *

    The style property or properties in the second parameter must be the + *

    JavaScript style property names. E.g. fontSize rather than font-size.

    + * + *

    The float style property will be unset by any of "float", + * "styleFloat", or "cssFloat".

    + * + * @method unset + * @param sel {String} the selector string to apply the changes to + * @param css {String|Array} style property name or Array of names + * @return {StyleSheet} the StyleSheet instance + * @chainable + */ + unset : function (sel,css) { + var rule = cssRules[sel], + multi = sel.split(/\s*,\s*/), + remove = !css, + rules, i; + + // IE's addRule doesn't support multiple comma delimited selectors + // so rules are mapped internally by atomic selectors + if (multi.length > 1) { + for (i = multi.length - 1; i >= 0; --i) { + this.unset(multi[i], css); + } + return this; + } + + if (rule) { + if (!remove) { + if (!lang.isArray(css)) { + css = [css]; + } + + workerStyle.cssText = rule.style.cssText; + for (i = css.length - 1; i >= 0; --i) { + _unsetProperty(workerStyle,css[i]); + } + + if (workerStyle.cssText) { + rule.style.cssText = workerStyle.cssText; + } else { + remove = true; + } + } + + if (remove) { // remove the rule altogether + rules = sheet[_rules]; + for (i = rules.length - 1; i >= 0; --i) { + if (rules[i] === rule) { + delete cssRules[sel]; + _deleteRule(i); + break; + } + } + } + } + return this; + }, + + /** + * Get the current cssText for a rule or the entire sheet. If the + * selector param is supplied, only the cssText for that rule will be + * returned, if found. If the selector string targets multiple + * selectors separated by commas, the cssText of the first rule only + * will be returned. If no selector string, the stylesheet's full + * cssText will be returned. + * + * @method getCssText + * @param sel {String} Selector string + * @return {String} + */ + getCssText : function (sel) { + var rule, css, selector; + + if (lang.isString(sel)) { + // IE's addRule doesn't support multiple comma delimited + // selectors so rules are mapped internally by atomic selectors + rule = cssRules[sel.split(/\s*,\s*/)[0]]; + + return rule ? rule.style.cssText : null; + } else { + css = []; + for (selector in cssRules) { + if (cssRules.hasOwnProperty(selector)) { + rule = cssRules[selector]; + css.push(rule.selectorText+" {"+rule.style.cssText+"}"); + } + } + return css.join("\n"); + } + } + },true); + +} + +_toCssText = function (css,base) { + var f = css.styleFloat || css.cssFloat || css['float'], + prop; + + // A very difficult to repro/isolate IE 9 beta (and Platform Preview 7) bug + // was reduced to this line throwing the error: + // "Invalid this pointer used as target for method call" + // It appears that the style collection is corrupted. The error is + // catchable, so in a best effort to work around it, replace the + // p and workerStyle and try the assignment again. + try { + workerStyle.cssText = base || ''; + } catch (ex) { + p = d.createElement('p'); + workerStyle = p.style; + workerStyle.cssText = base || ''; + } + + if (lang.isString(css)) { + // There is a danger here of incremental memory consumption in Opera + workerStyle.cssText += ';' + css; + } else { + if (f && !css[floatAttr]) { + css = lang.merge(css); + delete css.styleFloat; delete css.cssFloat; delete css['float']; + css[floatAttr] = f; + } + + for (prop in css) { + if (css.hasOwnProperty(prop)) { + try { + // IE throws Invalid Value errors and doesn't like whitespace + // in values ala ' red' or 'red ' + workerStyle[prop] = lang.trim(css[prop]); + } + catch (e) { + } + } + } + } + + return workerStyle.cssText; +}; + +lang.augmentObject(StyleSheet, { + /** + *

    Converts an object literal of style properties and values into a string + * of css text. This can then be assigned to el.style.cssText.

    + * + *

    The optional second parameter is a cssText string representing the + * starting state of the style prior to alterations. This is most often + * extracted from the eventual target's current el.style.cssText.

    + * + * @method StyleSheet.toCssText + * @param css {Object} object literal of style properties and values + * @param cssText {String} OPTIONAL starting cssText value + * @return {String} the resulting cssText string + * @static + */ + toCssText : (('opacity' in workerStyle) ? _toCssText : + // Wrap IE's toCssText to catch opacity. The copy/merge is to preserve + // the input object's integrity, but if float and opacity are set, the + // input will be copied twice in IE. Is there a way to avoid this + // without increasing the byte count? + function (css, cssText) { + if (lang.isObject(css) && 'opacity' in css) { + css = lang.merge(css,{ + filter: 'alpha(opacity='+(css.opacity*100)+')' + }); + delete css.opacity; + } + return _toCssText(css,cssText); + }), + + /** + * Registers a StyleSheet instance in the static registry by the given name + * + * @method StyleSheet.register + * @param name {String} the name to assign the StyleSheet in the registry + * @param sheet {StyleSheet} The StyleSheet instance + * @return {Boolean} false if no name or sheet is not a StyleSheet + * instance. true otherwise. + * @static + */ + register : function (name,sheet) { + return !!(name && sheet instanceof StyleSheet && + !sheets[name] && (sheets[name] = sheet)); + }, + + /** + *

    Determines if a selector string is safe to use. Used internally + * in set to prevent IE from locking up when attempting to add a rule for a + * "bad selector".

    + * + *

    Bad selectors are considered to be any string containing unescaped + * `~!@$%^&()+=|{}[];'"?< or space. Also forbidden are . or # followed by + * anything other than an alphanumeric. Additionally -abc or .-abc or + * #_abc or '# ' all fail. There are likely more failure cases, so + * please file a bug if you encounter one.

    + * + * @method StyleSheet.isValidSelector + * @param sel {String} the selector string + * @return {Boolean} + * @static + */ + isValidSelector : function (sel) { + var valid = false; + + if (sel && lang.isString(sel)) { + + if (!selectors.hasOwnProperty(sel)) { + // TEST: there should be nothing but white-space left after + // these destructive regexs + selectors[sel] = !/\S/.test( + // combinators + sel.replace(/\s+|\s*[+~>]\s*/g,' '). + // attribute selectors (contents not validated) + replace(/([^ ])\[.*?\]/g,'$1'). + // pseudo-class|element selectors (contents of parens + // such as :nth-of-type(2) or :not(...) not validated) + replace(/([^ ])::?[a-z][a-z\-]+[a-z](?:\(.*?\))?/ig,'$1'). + // element tags + replace(/(?:^| )[a-z0-6]+/ig,' '). + // escaped characters + replace(/\\./g,''). + // class and id identifiers + replace(/[.#]\w[\w\-]*/g,'')); + } + + valid = selectors[sel]; + } + + return valid; + } +},true); + +YAHOO.util.StyleSheet = StyleSheet; + +})(); + +/* + +NOTES + * Style node must be added to the head element. Safari does not honor styles + applied to StyleSheet objects on style nodes in the body. + * StyleSheet object is created on the style node when the style node is added + to the head element in Firefox 2 (and maybe 3?) + * The cssRules collection is replaced after insertRule/deleteRule calls in + Safari 3.1. Existing Rules are used in the new collection, so the collection + cannot be cached, but the rules can be. + * Opera requires that the index be passed with insertRule. + * Same-domain restrictions prevent modifying StyleSheet objects attached to + link elements with remote href (or "about:blank" or "javascript:false") + * Same-domain restrictions prevent reading StyleSheet cssRules/rules + collection of link elements with remote href (or "about:blank" or + "javascript:false") + * Same-domain restrictions result in Safari not populating node.sheet property + for link elements with remote href (et.al) + * IE names StyleSheet related properties and methods differently (see code) + * IE converts tag names to upper case in the Rule's selectorText + * IE converts empty string assignment to complex properties to value settings + for all child properties. E.g. style.background = '' sets non-'' values on + style.backgroundPosition, style.backgroundColor, etc. All else clear + style.background and all child properties. + * IE assignment style.filter = '' will result in style.cssText == 'FILTER:' + * All browsers support Rule.style.cssText as a read/write property, leaving + only opacity needing to be accounted for. + * Benchmarks of style.property = value vs style.cssText += 'property: value' + indicate cssText is slightly slower for single property assignment. For + multiple property assignment, cssText speed stays relatively the same where + style.property speed decreases linearly by the number of properties set. + Exception being Opera 9.27, where style.property is always faster than + style.cssText. + * Opera 9.5b throws a syntax error when assigning cssText with a syntax error. + * Opera 9.5 doesn't honor rule.style.cssText = ''. Previous style persists. + You have to remove the rule altogether. + * Stylesheet properties set with !important will trump inline style set on an + element or in el.style.property. + * Creating a worker style collection like document.createElement('p').style; + will fail after a time in FF (~5secs of inactivity). Property assignments + will not alter the property or cssText. It may be the generated node is + garbage collected and the style collection becomes inert (speculation). + * IE locks up when attempting to add a rule with a selector including at least + characters {[]}~`!@%^&*()+=|? (unescaped) and leading _ or - + such as addRule('-foo','{ color: red }') or addRule('._abc','{...}') + * IE's addRule doesn't support comma separated selectors such as + addRule('.foo, .bar','{..}') + * IE throws an error on valid values with leading/trailing white space. + * When creating an entire sheet at once, only FF2/3 & Opera allow creating a + style node, setting its innerHTML and appending to head. + * When creating an entire sheet at once, Safari requires the style node to be + created with content in innerHTML of another element. + * When creating an entire sheet at once, IE requires the style node content to + be set via node.styleSheet.cssText + * When creating an entire sheet at once in IE, styleSheet.cssText can't be + written until node.type = 'text/css'; is performed. + * When creating an entire sheet at once in IE, load-time fork on + var styleNode = d.createElement('style'); _method = styleNode.styleSheet ?.. + fails (falsey). During run-time, the test for .styleSheet works fine + * Setting complex properties in cssText will SOMETIMES allow child properties + to be unset + set unset FF2 FF3 S3.1 IE6 IE7 Op9.27 Op9.5 + ---------- ----------------- --- --- ---- --- --- ------ ----- + border -top NO NO YES YES YES YES YES + -top-color NO NO YES YES YES + -color NO NO NO NO NO + background -color NO NO YES YES YES + -position NO NO YES YES YES + -position-x NO NO NO NO NO + font line-height YES YES NO NO NO NO YES + -style YES YES NO YES YES + -size YES YES NO YES YES + -size-adjust ??? ??? n/a n/a n/a ??? ??? + padding -top NO NO YES YES YES + margin -top NO NO YES YES YES + list-style -type YES YES YES YES YES + -position YES YES YES YES YES + overflow -x NO NO YES n/a YES + + ??? - unsetting font-size-adjust has the same effect as unsetting font-size + * FireFox and WebKit populate rule.cssText as "SELECTOR { CSSTEXT }", but + Opera and IE do not. + * IE6 and IE7 silently ignore the { and } if passed into addRule('.foo','{ + color:#000}',0). IE8 does not and creates an empty rule. + * IE6-8 addRule('.foo','',n) throws an error. Must supply *some* cssText +*/ + +YAHOO.register("stylesheet", YAHOO.util.StyleSheet, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/utilities/utilities.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/utilities/utilities.js new file mode 100644 index 0000000..7377991 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/utilities/utilities.js @@ -0,0 +1,39 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var b=arguments,g=null,e,c,f;for(e=0;e":">",'"':""","'":"'","/":"/","`":"`"},d=["toString","valueOf"],e={isArray:function(j){return a.toString.apply(j)===c;},isBoolean:function(j){return typeof j==="boolean";},isFunction:function(j){return(typeof j==="function")||a.toString.apply(j)===h;},isNull:function(j){return j===null;},isNumber:function(j){return typeof j==="number"&&isFinite(j);},isObject:function(j){return(j&&(typeof j==="object"||f.isFunction(j)))||false;},isString:function(j){return typeof j==="string";},isUndefined:function(j){return typeof j==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(l,k){var j,n,m;for(j=0;j"'\/`]/g,function(k){return g[k];});},extend:function(m,n,l){if(!n||!m){throw new Error("extend failed, please check that "+"all dependencies are included.");}var k=function(){},j;k.prototype=n.prototype;m.prototype=new k();m.prototype.constructor=m;m.superclass=n.prototype;if(n.prototype.constructor==a.constructor){n.prototype.constructor=n;}if(l){for(j in l){if(f.hasOwnProperty(l,j)){m.prototype[j]=l[j];}}f._IEEnumFix(m.prototype,l);}},augmentObject:function(n,m){if(!m||!n){throw new Error("Absorb failed, verify dependencies.");}var j=arguments,l,o,k=j[2];if(k&&k!==true){for(l=2;l0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}if(r.length>1){r.pop();}r.push("]");}else{r.push("{");for(l in j){if(f.hasOwnProperty(j,l)){r.push(l+m);if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}}if(r.length>1){r.pop();}r.push("}");}return r.join("");},substitute:function(x,y,E,l){var D,C,B,G,t,u,F=[],p,z=x.length,A="dump",r=" ",q="{",m="}",n,w;for(;;){D=x.lastIndexOf(q,z);if(D<0){break;}C=x.indexOf(m,D);if(D+1>C){break;}p=x.substring(D+1,C);G=p;u=null;B=G.indexOf(r);if(B>-1){u=G.substring(B+1);G=G.substring(0,B);}t=y[G];if(E){t=E(G,t,u);}if(f.isObject(t)){if(f.isArray(t)){t=f.dump(t,parseInt(u,10));}else{u=u||"";n=u.indexOf(A);if(n>-1){u=u.substring(4);}w=t.toString();if(w===i||n>-1){t=f.dump(t,parseInt(u,10));}else{t=w;}}}else{if(!f.isString(t)&&!f.isNumber(t)){t="~-"+F.length+"-~";F[F.length]=p;}}x=x.substring(0,D)+t+x.substring(C+1);if(l===false){z=D-1;}}for(D=F.length-1;D>=0;D=D-1){x=x.replace(new RegExp("~-"+D+"-~"),"{"+F[D]+"}","g");}return x;},trim:function(j){try{return j.replace(/^\s+|\s+$/g,"");}catch(k){return j; +}},merge:function(){var n={},k=arguments,j=k.length,m;for(m=0;m=420){z.addEventListener("load",function(){YAHOO.log(x+" DOM2 onload "+u,"info","Get");F(x,u);});}else{t=m[x];if(t.varName){v=YAHOO.util.Get.POLL_FREQ;YAHOO.log("Polling for "+t.varName[0]);t.maxattempts=YAHOO.util.Get.TIMEOUT/v;t.attempts=0;t._cache=t.varName[0].split(".");t.timer=s.later(v,t,function(w){I=this._cache;A=I.length;J=this.win;for(C=0;Cthis.maxattempts){y="Over retry limit, giving up";t.timer.cancel();q(x,y);}else{YAHOO.log(I[C]+" failed, retrying");}return;}}YAHOO.log("Safari poll complete");t.timer.cancel();F(x,u);},null,true);}else{s.later(YAHOO.util.Get.POLL_FREQ,null,F,[x,u]);}}}}else{z.onload=function(){YAHOO.log(x+" onload "+u,"info","Get");F(x,u);};}}};q=function(w,v){YAHOO.log("get failure: "+v,"warn","Get");var u=m[w],t;if(u.onFailure){t=u.scope||u.win;u.onFailure.call(t,a(u,v));}};d=function(z){if(m[z]){var t=m[z],u=t.nodes,x=u.length,C=t.win.document,A=C.getElementsByTagName("head")[0],v,y,w,B;if(t.insertBefore){v=b(t.insertBefore,z);if(v){A=v.parentNode;}}for(y=0;y=m.rollup);if(roll){break;}}}}}else{for(j=0;j=m.rollup);if(roll){break;}}}}}if(roll){r[i]=true;rolled=true;this.getRequires(m);}}}if(!rolled){break;}}},_reduce:function(){var i,j,s,m,r=this.required;for(i in r){if(i in this.loaded){delete r[i];}else{var skinDef=this.parseSkin(i);if(skinDef){if(!skinDef.module){var skin_pre=this.SKIN_PREFIX+skinDef.skin;for(j in r){if(lang.hasOwnProperty(r,j)){m=this.moduleInfo[j];var ext=m&&m.ext;if(!ext&&j!==i&&j.indexOf(skin_pre)>-1){delete r[j];}}}}}else{m=this.moduleInfo[i];s=m&&m.supersedes;if(s){for(j=0;j-1){return true;}if(after&&YUI.ArrayUtil.indexOf(after,bb)>-1){return true;}if(checkOptional&&optional&&YUI.ArrayUtil.indexOf(optional,bb)>-1){return true;}var ss=info[bb]&&info[bb].supersedes;if(ss){for(ii=0;iistartLen){YAHOO.util.Get.script(self._filter(js),{data:self._loading,onSuccess:callback,onFailure:self._onFailure,onTimeout:self._onTimeout,insertBefore:self.insertBefore,charset:self.charset,timeout:self.timeout,scope:self});}else{this.loadNext();}};if(css.length>startLen){YAHOO.util.Get.css(this._filter(css),{data:this._loading,onSuccess:loadScript,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,scope:self});}else{loadScript();}return;}else{this.loadNext(this._loading);}},insert:function(o,type){this.calculate(o);this._loading=true;this.loadType=type;if(this.combine){return this._combine();}if(!type){var self=this;this._internalCallback=function(){self._internalCallback=null;self.insert(null,"js");};this.insert(null,"css");return;}this.loadNext();},sandbox:function(o,type){var self=this,success=function(o){var idx=o.argument[0],name=o.argument[2];self._scriptText[idx]=o.responseText;if(self.onProgress){self.onProgress.call(self.scope,{name:name,scriptText:o.responseText,xhrResponse:o,data:self.data});}self._loadCount++;if(self._loadCount>=self._stopCount){var v=self.varName||"YAHOO";var t="(function() {\n";var b="\nreturn "+v+";\n})();";var ref=eval(t+self._scriptText.join("\n")+b);self._pushEvents(ref);if(ref){self.onSuccess.call(self.scope,{reference:ref,data:self.data});}else{self._onFailure.call(self.varName+" reference failure");}}},failure=function(o){self.onFailure.call(self.scope,{msg:"XHR failure",xhrResponse:o,data:self.data});};self._config(o);if(!self.onSuccess){throw new Error("You must supply an onSuccess handler for your sandbox");}self._sandbox=true;if(!type||type!=="js"){self._internalCallback=function(){self._internalCallback=null;self.sandbox(null,"js");};self.insert(null,"css");return;}if(!util.Connect){var ld=new YAHOO.util.YUILoader();ld.insert({base:self.base,filter:self.filter,require:"connection",insertBefore:self.insertBefore,charset:self.charset,onSuccess:function(){self.sandbox(null,"js");},scope:self},"js");return;}self._scriptText=[];self._loadCount=0;self._stopCount=self.sorted.length;self._xhr=[];self.calculate();var s=self.sorted,l=s.length,i,m,url;for(i=0;i-1;}}else{}return G;},addClass:function(W,G){return e.Dom.batch(W,e.Dom._addClass,G);},_addClass:function(X,W){var G=false,Y;if(X&&W){Y=e.Dom._getAttribute(X,f)||i;if(!e.Dom._hasClass(X,W)){e.Dom.setAttribute(X,f,a(Y+b+W));G=true;}}else{}return G;},removeClass:function(W,G){return e.Dom.batch(W,e.Dom._removeClass,G);},_removeClass:function(Y,X){var W=false,aa,Z,G;if(Y&&X){aa=e.Dom._getAttribute(Y,f)||i;e.Dom.setAttribute(Y,f,aa.replace(e.Dom._getClassRegex(X),i));Z=e.Dom._getAttribute(Y,f);if(aa!==Z){e.Dom.setAttribute(Y,f,a(Z));W=true;if(e.Dom._getAttribute(Y,f)===""){G=(Y.hasAttribute&&Y.hasAttribute(E))?E:f;Y.removeAttribute(G);}}}else{}return W;},replaceClass:function(X,W,G){return e.Dom.batch(X,e.Dom._replaceClass,{from:W,to:G});},_replaceClass:function(Y,X){var W,ab,aa,G=false,Z;if(Y&&X){ab=X.from;aa=X.to;if(!aa){G=false;}else{if(!ab){G=e.Dom._addClass(Y,X.to);}else{if(ab!==aa){Z=e.Dom._getAttribute(Y,f)||i;W=(b+Z.replace(e.Dom._getClassRegex(ab),b+aa).replace(/\s+/g,b)).split(e.Dom._getClassRegex(aa));W.splice(1,0,b+aa);e.Dom.setAttribute(Y,f,a(W.join(i)));G=true;}}}}else{}return G;},generateId:function(G,X){X=X||"yui-gen";var W=function(Y){if(Y&&Y.id){return Y.id;}var Z=X+YAHOO.env._id_counter++; +if(Y){if(Y[C]&&Y[C].getElementById(Z)){return e.Dom.generateId(Y,Z+X);}Y.id=Z;}return Z;};return e.Dom.batch(G,W,e.Dom,true)||W.apply(e.Dom,arguments);},isAncestor:function(W,X){W=e.Dom.get(W);X=e.Dom.get(X);var G=false;if((W&&X)&&(W[K]&&X[K])){if(W.contains&&W!==X){G=W.contains(X);}else{if(W.compareDocumentPosition){G=!!(W.compareDocumentPosition(X)&16);}}}else{}return G;},inDocument:function(G,W){return e.Dom._inDoc(e.Dom.get(G),W);},_inDoc:function(W,X){var G=false;if(W&&W[c]){X=X||W[C];G=e.Dom.isAncestor(X[U],W);}else{}return G;},getElementsBy:function(W,af,ab,ad,X,ac,ae){af=af||"*";ab=(ab)?e.Dom.get(ab):null||j;var aa=(ae)?null:[],G;if(ab){G=ab.getElementsByTagName(af);for(var Y=0,Z=G.length;Y=8){e.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(d,e,a,c){this.top=d;this.y=d;this[1]=d;this.right=e;this.bottom=a;this.left=c;this.x=c;this[0]=c;this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(a){return(a.left>=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(f){var d=Math.max(this.top,f.top),e=Math.min(this.right,f.right),a=Math.min(this.bottom,f.bottom),c=Math.max(this.left,f.left); +if(a>=d&&e>=c){return new YAHOO.util.Region(d,e,a,c);}else{return null;}};YAHOO.util.Region.prototype.union=function(f){var d=Math.min(this.top,f.top),e=Math.max(this.right,f.right),a=Math.max(this.bottom,f.bottom),c=Math.min(this.left,f.left);return new YAHOO.util.Region(d,e,a,c);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(e){var g=YAHOO.util.Dom.getXY(e),d=g[1],f=g[0]+e.offsetWidth,a=g[1]+e.offsetHeight,c=g[0];return new YAHOO.util.Region(d,f,a,c);};YAHOO.util.Point=function(a,b){if(YAHOO.lang.isArray(a)){b=a[1];a=a[0];}YAHOO.util.Point.superclass.constructor.call(this,b,a,b,a);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var b=YAHOO.util,a="clientTop",f="clientLeft",j="parentNode",k="right",w="hasLayout",i="px",u="opacity",l="auto",d="borderLeftWidth",g="borderTopWidth",p="borderRightWidth",v="borderBottomWidth",s="visible",q="transparent",n="height",e="width",h="style",t="currentStyle",r=/^width|height$/,o=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,m={get:function(x,z){var y="",A=x[t][z];if(z===u){y=b.Dom.getStyle(x,u);}else{if(!A||(A.indexOf&&A.indexOf(i)>-1)){y=A;}else{if(b.Dom.IE_COMPUTED[z]){y=b.Dom.IE_COMPUTED[z](x,z);}else{if(o.test(A)){y=b.Dom.IE.ComputedStyle.getPixel(x,z);}else{y=A;}}}}return y;},getOffset:function(z,E){var B=z[t][E],x=E.charAt(0).toUpperCase()+E.substr(1),C="offset"+x,y="pixel"+x,A="",D;if(B==l){D=z[C];if(D===undefined){A=0;}A=D;if(r.test(E)){z[h][E]=D;if(z[C]>D){A=D-(z[C]-D);}z[h][E]=l;}}else{if(!z[h][y]&&!z[h][E]){z[h][E]=B;}A=z[h][y];}return A+i;},getBorderWidth:function(x,z){var y=null;if(!x[t][w]){x[h].zoom=1;}switch(z){case g:y=x[a];break;case v:y=x.offsetHeight-x.clientHeight-x[a];break;case d:y=x[f];break;case p:y=x.offsetWidth-x.clientWidth-x[f];break;}return y+i;},getPixel:function(y,x){var A=null,B=y[t][k],z=y[t][x];y[h][k]=z;A=y[h].pixelRight;y[h][k]=B;return A+i;},getMargin:function(y,x){var z;if(y[t][x]==l){z=0+i;}else{z=b.Dom.IE.ComputedStyle.getPixel(y,x);}return z;},getVisibility:function(y,x){var z;while((z=y[t])&&z[x]=="inherit"){y=y[j];}return(z)?z[x]:s;},getColor:function(y,x){return b.Dom.Color.toRGB(y[t][x])||q;},getBorderColor:function(y,x){var z=y[t],A=z[x]||z.color;return b.Dom.Color.toRGB(b.Dom.Color.toHex(A));}},c={};c.top=c.right=c.bottom=c.left=c[e]=c[n]=m.getOffset;c.color=m.getColor;c[g]=c[p]=c[v]=c[d]=m.getBorderWidth;c.marginTop=c.marginRight=c.marginBottom=c.marginLeft=m.getMargin;c.visibility=m.getVisibility;c.borderColor=c.borderTopColor=c.borderRightColor=c.borderBottomColor=c.borderLeftColor=m.getBorderColor;b.Dom.IE_COMPUTED=c;b.Dom.IE_ComputedStyle=m;})();(function(){var c="toString",a=parseInt,b=RegExp,d=YAHOO.util;d.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(e){if(!d.Dom.Color.re_RGB.test(e)){e=d.Dom.Color.toHex(e);}if(d.Dom.Color.re_hex.exec(e)){e="rgb("+[a(b.$1,16),a(b.$2,16),a(b.$3,16)].join(", ")+")";}return e;},toHex:function(f){f=d.Dom.Color.KEYWORDS[f]||f;if(d.Dom.Color.re_RGB.exec(f)){f=[Number(b.$1).toString(16),Number(b.$2).toString(16),Number(b.$3).toString(16)];for(var e=0;e0){i=c[0];}try{b=g.fn.call(f,i,g.obj);}catch(h){this.lastError=h;if(a){throw h;}}}else{try{b=g.fn.call(f,this.type,c,g.obj);}catch(d){this.lastError=d;if(a){throw d;}}}return b;},unsubscribeAll:function(){var a=this.subscribers.length,b;for(b=a-1;b>-1;b--){this._delete(b);}this.subscribers=[];return a;},_delete:function(a){var b=this.subscribers[a];if(b){delete b.fn;delete b.obj;}this.subscribers.splice(a,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(a,b,c){this.fn=a;this.obj=YAHOO.lang.isUndefined(b)?null:b;this.overrideContext=c;};YAHOO.util.Subscriber.prototype.getScope=function(a){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return a;};YAHOO.util.Subscriber.prototype.contains=function(a,b){if(b){return(this.fn==a&&this.obj==b);}else{return(this.fn==a);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var g=false,h=[],j=[],a=0,e=[],b=0,c={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},d=YAHOO.env.ua.ie,f="focusin",i="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:d,_interval:null,_dri:null,_specialTypes:{focusin:(d?"focusin":"focus"),focusout:(d?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(q,m,o,p,n){var k=(YAHOO.lang.isString(q))?[q]:q;for(var l=0;l-1;m--){s=(this.removeListener(l[m],k,r)&&s);}return s;}}if(!r||!r.call){return this.purgeElement(l,false,k);}if("unload"==k){for(m=j.length-1;m>-1;m--){u=j[m];if(u&&u[0]==l&&u[1]==k&&u[2]==r){j.splice(m,1);return true;}}return false;}var n=null;var o=arguments[3];if("undefined"===typeof o){o=this._getCacheIndex(h,l,k,r);}if(o>=0){n=h[o];}if(!l||!n){return false;}var t=n[this.CAPTURE]===true?true:false;try{this._simpleRemove(l,k,n[this.WFN],t);}catch(q){this.lastError=q;return false;}delete h[o][this.WFN];delete h[o][this.FN];h.splice(o,1);return true;},getTarget:function(m,l){var k=m.target||m.srcElement;return this.resolveTextNode(k);},resolveTextNode:function(l){try{if(l&&3==l.nodeType){return l.parentNode;}}catch(k){return null;}return l;},getPageX:function(l){var k=l.pageX;if(!k&&0!==k){k=l.clientX||0;if(this.isIE){k+=this._getScrollLeft();}}return k;},getPageY:function(k){var l=k.pageY;if(!l&&0!==l){l=k.clientY||0;if(this.isIE){l+=this._getScrollTop();}}return l;},getXY:function(k){return[this.getPageX(k),this.getPageY(k)];},getRelatedTarget:function(l){var k=l.relatedTarget; +if(!k){if(l.type=="mouseout"){k=l.toElement;}else{if(l.type=="mouseover"){k=l.fromElement;}}}return this.resolveTextNode(k);},getTime:function(m){if(!m.time){var l=new Date().getTime();try{m.time=l;}catch(k){this.lastError=k;return l;}}return m.time;},stopEvent:function(k){this.stopPropagation(k);this.preventDefault(k);},stopPropagation:function(k){if(k.stopPropagation){k.stopPropagation();}else{k.cancelBubble=true;}},preventDefault:function(k){if(k.preventDefault){k.preventDefault();}else{k.returnValue=false;}},getEvent:function(m,k){var l=m||window.event;if(!l){var n=this.getEvent.caller;while(n){l=n.arguments[0];if(l&&Event==l.constructor){break;}n=n.caller;}}return l;},getCharCode:function(l){var k=l.keyCode||l.charCode||0;if(YAHOO.env.ua.webkit&&(k in c)){k=c[k];}return k;},_getCacheIndex:function(n,q,r,p){for(var o=0,m=n.length;o0&&e.length>0);}var p=[];var r=function(t,u){var s=t;if(u.overrideContext){if(u.overrideContext===true){s=u.obj;}else{s=u.overrideContext;}}u.fn.call(s,u.obj);};var l,k,o,n,m=[];for(l=0,k=e.length;l-1;l--){o=e[l];if(!o||!o.id){e.splice(l,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(p,q,s){var n=(YAHOO.lang.isString(p))?this.getEl(p):p;var r=this.getListeners(n,s),o,k;if(r){for(o=r.length-1;o>-1;o--){var m=r[o];this.removeListener(n,m.type,m.fn);}}if(q&&n&&n.childNodes){for(o=0,k=n.childNodes.length;o-1;o--){n=h[o];if(n){try{m.removeListener(n[m.EL],n[m.TYPE],n[m.FN],o);}catch(v){}}}n=null;}try{m._simpleRemove(window,"unload",m._unload);m._simpleRemove(window,"load",m._load);}catch(u){}},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var k=document.documentElement,l=document.body;if(k&&(k.scrollTop||k.scrollLeft)){return[k.scrollTop,k.scrollLeft];}else{if(l){return[l.scrollTop,l.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(m,n,l,k){m.addEventListener(n,l,(k));};}else{if(window.attachEvent){return function(m,n,l,k){m.attachEvent("on"+n,l);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(m,n,l,k){m.removeEventListener(n,l,(k));};}else{if(window.detachEvent){return function(l,m,k){l.detachEvent("on"+m,k);};}else{return function(){};}}}()};}();(function(){var a=YAHOO.util.Event;a.on=a.addListener;a.onFocus=a.addFocusListener;a.onBlur=a.addBlurListener; +/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ +if(a.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;a._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var b=document.createElement("p");a._dri=setInterval(function(){try{b.doScroll("left");clearInterval(a._dri);a._dri=null;a._ready();b=null;}catch(c){}},a.POLL_INTERVAL);}}else{if(a.webkit&&a.webkit<525){a._dri=setInterval(function(){var c=document.readyState;if("loaded"==c||"complete"==c){clearInterval(a._dri);a._dri=null;a._ready();}},a.POLL_INTERVAL);}else{a._simpleAdd(document,"DOMContentLoaded",a._ready);}}a._simpleAdd(window,"load",a._load);a._simpleAdd(window,"unload",a._unload);a._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(a,c,f,e){this.__yui_events=this.__yui_events||{};var d=this.__yui_events[a];if(d){d.subscribe(c,f,e);}else{this.__yui_subscribers=this.__yui_subscribers||{};var b=this.__yui_subscribers;if(!b[a]){b[a]=[];}b[a].push({fn:c,obj:f,overrideContext:e});}},unsubscribe:function(c,e,g){this.__yui_events=this.__yui_events||{};var a=this.__yui_events;if(c){var f=a[c];if(f){return f.unsubscribe(e,g);}}else{var b=true;for(var d in a){if(YAHOO.lang.hasOwnProperty(a,d)){b=b&&a[d].unsubscribe(e,g); +}}return b;}return false;},unsubscribeAll:function(a){return this.unsubscribe(a);},createEvent:function(b,g){this.__yui_events=this.__yui_events||{};var e=g||{},d=this.__yui_events,f;if(d[b]){}else{f=new YAHOO.util.CustomEvent(b,e.scope||this,e.silent,YAHOO.util.CustomEvent.FLAT,e.fireOnce);d[b]=f;if(e.onSubscribeCallback){f.subscribeEvent.subscribe(e.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var a=this.__yui_subscribers[b];if(a){for(var c=0;c=200&&f<300)||f===1223||c){a=b.xdr?b.r:this.createResponseObject(b,h);if(j&&j.success){if(!j.scope){j.success(a);}else{j.success.apply(j.scope,[a]);}}this.successEvent.fire(a);if(b.successEvent){b.successEvent.fire(a);}}else{switch(f){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:a=this.createExceptionObject(b.tId,h,(d?d:false));if(j&&j.failure){if(!j.scope){j.failure(a);}else{j.failure.apply(j.scope,[a]);}}break;default:a=(b.xdr)?b.response:this.createResponseObject(b,h);if(j&&j.failure){if(!j.scope){j.failure(a);}else{j.failure.apply(j.scope,[a]);}}}this.failureEvent.fire(a);if(b.failureEvent){b.failureEvent.fire(a);}}this.releaseObject(b);a=null;},createResponseObject:function(a,h){var d={},k={},f,c,g,b;try{c=a.conn.getAllResponseHeaders();g=c.split("\n");for(f=0;f'+''+''+"
    ",k=document.createElement("div");document.body.appendChild(k);k.innerHTML=j;}function b(l,i,j,n,k){h[parseInt(l.tId)]={"o":l,"c":n};if(k){n.method=i;n.data=k;}l.conn.send(j,n,l.tId);}function e(i){d(i);g._transport=document.getElementById("YUIConnectionSwf");}function c(){g.xdrReadyEvent.fire();}function a(j,i){if(j){g.startEvent.fire(j,i.argument);if(j.startEvent){j.startEvent.fire(j,i.argument);}}}function f(j){var k=h[j.tId].o,i=h[j.tId].c;if(j.statusText==="xdr:start"){a(k,i);return;}j.responseText=decodeURI(j.responseText);k.r=j;if(i.argument){k.r.argument=i.argument;}this.handleTransactionResponse(k,i,j.statusText==="xdr:abort"?true:false);delete h[j.tId];}g.xdr=b;g.swf=d;g.transport=e;g.xdrReadyEvent=new YAHOO.util.CustomEvent("xdrReady");g.xdrReady=c;g.handleXdrResponse=f;})();(function(){var e=YAHOO.util.Connect,g=YAHOO.util.Event,a=document.documentMode?document.documentMode:false;e._isFileUpload=false;e._formNode=null;e._sFormData=null;e._submitElementValue=null;e.uploadEvent=new YAHOO.util.CustomEvent("upload");e._hasSubmitListener=function(){if(g){g.addListener(document,"click",function(k){var j=g.getTarget(k),i=j.nodeName.toLowerCase();if((i==="input"||i==="button")&&(j.type&&j.type.toLowerCase()=="submit")){e._submitElementValue=encodeURIComponent(j.name)+"="+encodeURIComponent(j.value);}});return true;}return false;}();function h(w,r,m){var v,l,u,s,z,t=false,p=[],y=0,o,q,n,x,k;this.resetFormState();if(typeof w=="string"){v=(document.getElementById(w)||document.forms[w]);}else{if(typeof w=="object"){v=w;}else{return;}}if(r){this.createFrame(m?m:null);this._isFormSubmit=true;this._isFileUpload=true;this._formNode=v;return;}for(o=0,q=v.elements.length;o-1){k=l.options[l.selectedIndex];p[y++]=u+encodeURIComponent((k.attributes.value&&k.attributes.value.specified)?k.value:k.text);}break;case"select-multiple":if(l.selectedIndex>-1){for(n=l.selectedIndex,x=l.options.length;n');if(typeof i=="boolean"){k.src="javascript:false";}}else{k=document.createElement("iframe");k.id=j;k.name=j;}k.style.position="absolute";k.style.top="-1000px";k.style.left="-1000px";document.body.appendChild(k);}function f(j){var m=[],k=j.split("&"),l,n;for(l=0;l=8)?true:false,z=this,v=(y&&y.argument)?y.argument:null,x,s,k,r,j,q;j={action:this._formNode.getAttribute("action"),method:this._formNode.getAttribute("method"),target:this._formNode.getAttribute("target")};this._formNode.setAttribute("action",n);this._formNode.setAttribute("method","POST");this._formNode.setAttribute("target",t);if(YAHOO.env.ua.ie&&!p){this._formNode.setAttribute("encoding",u);}else{this._formNode.setAttribute("enctype",u);}if(l){x=this.appendPostData(l);}this._formNode.submit();this.startEvent.fire(m,v);if(m.startEvent){m.startEvent.fire(m,v);}if(y&&y.timeout){this._timeOut[m.tId]=window.setTimeout(function(){z.abort(m,y,true);},y.timeout);}if(x&&x.length>0){for(s=0;s0)?f:0;}if(c in d&&!("style" in d&&c in d.style)){d[c]=f;}else{b.Dom.setStyle(d,c,f+e);}},getAttribute:function(c){var e=this.getEl();var g=b.Dom.getStyle(e,c);if(g!=="auto"&&!this.patterns.offsetUnit.test(g)){return parseFloat(g);}var d=this.patterns.offsetAttribute.exec(c)||[];var h=!!(d[3]);var f=!!(d[2]);if("style" in e){if(f||(b.Dom.getStyle(e,"position")=="absolute"&&h)){g=e["offset"+d[0].charAt(0).toUpperCase()+d[0].substr(1)];}else{g=0;}}else{if(c in e){g=e[c];}}return g;},getDefaultUnit:function(c){if(this.patterns.defaultUnit.test(c)){return"px";}return"";},setRuntimeAttribute:function(d){var j;var e;var f=this.attributes;this.runtimeAttributes[d]={};var h=function(i){return(typeof i!=="undefined");};if(!h(f[d]["to"])&&!h(f[d]["by"])){return false;}j=(h(f[d]["from"]))?f[d]["from"]:this.getAttribute(d);if(h(f[d]["to"])){e=f[d]["to"];}else{if(h(f[d]["by"])){if(j.constructor==Array){e=[];for(var g=0,c=j.length;g0&&isFinite(o)){if(k.currentFrame+o>=n){o=n-(m+1);}k.currentFrame+=o;}};this._queue=c;this._getIndex=a;};YAHOO.util.Bezier=new function(){this.getPosition=function(e,d){var f=e.length;var c=[];for(var b=0;b0&&!(m[0] instanceof Array)){m=[m];}else{var l=[];for(n=0,p=m.length;n0){this.runtimeAttributes[q]=this.runtimeAttributes[q].concat(m);}this.runtimeAttributes[q][this.runtimeAttributes[q].length]=j;}else{f.setRuntimeAttribute.call(this,q);}};var b=function(g,i){var h=e.Dom.getXY(this.getEl());g=[g[0]-h[0]+i[0],g[1]-h[1]+i[1]];return g;};var d=function(g){return(typeof g!=="undefined");};e.Motion=a;})();(function(){var d=function(f,e,g,h){if(f){d.superclass.constructor.call(this,f,e,g,h);}};d.NAME="Scroll";var b=YAHOO.util;YAHOO.extend(d,b.ColorAnim);var c=d.superclass;var a=d.prototype;a.doMethod=function(e,h,f){var g=null;if(e=="scroll"){g=[this.method(this.currentFrame,h[0],f[0]-h[0],this.totalFrames),this.method(this.currentFrame,h[1],f[1]-h[1],this.totalFrames)];}else{g=c.doMethod.call(this,e,h,f);}return g;};a.getAttribute=function(e){var g=null;var f=this.getEl();if(e=="scroll"){g=[f.scrollLeft,f.scrollTop];}else{g=c.getAttribute.call(this,e);}return g;};a.setAttribute=function(e,h,g){var f=this.getEl();if(e=="scroll"){f.scrollLeft=h[0];f.scrollTop=h[1];}else{c.setAttribute.call(this,e,h,g);}};b.Scroll=d;})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.9.0",build:"2800"});if(!YAHOO.util.DragDropMgr){YAHOO.util.DragDropMgr=function(){var A=YAHOO.util.Event,B=YAHOO.util.Dom;return{useShim:false,_shimActive:false,_shimState:false,_debugShim:false,_createShim:function(){var C=document.createElement("div");C.id="yui-ddm-shim";if(document.body.firstChild){document.body.insertBefore(C,document.body.firstChild);}else{document.body.appendChild(C);}C.style.display="none";C.style.backgroundColor="red";C.style.position="absolute";C.style.zIndex="99999";B.setStyle(C,"opacity","0");this._shim=C;A.on(C,"mouseup",this.handleMouseUp,this,true);A.on(C,"mousemove",this.handleMouseMove,this,true);A.on(window,"scroll",this._sizeShim,this,true);},_sizeShim:function(){if(this._shimActive){var C=this._shim;C.style.height=B.getDocumentHeight()+"px";C.style.width=B.getDocumentWidth()+"px";C.style.top="0";C.style.left="0";}},_activateShim:function(){if(this.useShim){if(!this._shim){this._createShim();}this._shimActive=true;var C=this._shim,D="0";if(this._debugShim){D=".5";}B.setStyle(C,"opacity",D);this._sizeShim();C.style.display="block";}},_deactivateShim:function(){this._shim.style.display="none";this._shimActive=false;},_shim:null,ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,interactionInfo:null,init:function(){this.initialized=true;},POINT:0,INTERSECT:1,STRICT_INTERSECT:2,mode:0,_execOnAll:function(E,D){for(var F in this.ids){for(var C in this.ids[F]){var G=this.ids[F][C];if(!this.isTypeOfDD(G)){continue;}G[E].apply(G,D);}}},_onLoad:function(){this.init();A.on(document,"mouseup",this.handleMouseUp,this,true);A.on(document,"mousemove",this.handleMouseMove,this,true);A.on(window,"unload",this._onUnload,this,true);A.on(window,"resize",this._onResize,this,true);},_onResize:function(C){this._execOnAll("resetConstraints",[]);},lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isLocked:function(){return this.locked;},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:1000,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,fromTimeout:false,regDragDrop:function(D,C){if(!this.initialized){this.init();}if(!this.ids[C]){this.ids[C]={};}this.ids[C][D.id]=D;},removeDDFromGroup:function(E,C){if(!this.ids[C]){this.ids[C]={};}var D=this.ids[C];if(D&&D[E.id]){delete D[E.id];}},_remove:function(E){for(var D in E.groups){if(D){var C=this.ids[D];if(C&&C[E.id]){delete C[E.id];}}}delete this.handleIds[E.id];},regHandle:function(D,C){if(!this.handleIds[D]){this.handleIds[D]={};}this.handleIds[D][C]=C;},isDragDrop:function(C){return(this.getDDById(C))?true:false;},getRelated:function(H,D){var G=[];for(var F in H.groups){for(var E in this.ids[F]){var C=this.ids[F][E];if(!this.isTypeOfDD(C)){continue;}if(!D||C.isTarget){G[G.length]=C;}}}return G;},isLegalTarget:function(G,F){var D=this.getRelated(G,true);for(var E=0,C=D.length;Ethis.clickPixelThresh||D>this.clickPixelThresh){this.startDrag(this.startX,this.startY);}}if(this.dragThreshMet){if(C&&C.events.b4Drag){C.b4Drag(F);C.fireEvent("b4DragEvent",{e:F});}if(C&&C.events.drag){C.onDrag(F);C.fireEvent("dragEvent",{e:F});}if(C){this.fireEvents(F,false);}}this.stopEvent(F);}},fireEvents:function(W,M){var c=this.dragCurrent;if(!c||c.isLocked()||c.dragOnly){return;}var O=YAHOO.util.Event.getPageX(W),N=YAHOO.util.Event.getPageY(W),Q=new YAHOO.util.Point(O,N),K=c.getTargetCoord(Q.x,Q.y),F=c.getDragEl(),E=["out","over","drop","enter"],V=new YAHOO.util.Region(K.y,K.x+F.offsetWidth,K.y+F.offsetHeight,K.x),I=[],D={},L={},R=[],d={outEvts:[],overEvts:[],dropEvts:[],enterEvts:[]};for(var T in this.dragOvers){var f=this.dragOvers[T];if(!this.isTypeOfDD(f)){continue; +}if(!this.isOverTarget(Q,f,this.mode,V)){d.outEvts.push(f);}I[T]=true;delete this.dragOvers[T];}for(var S in c.groups){if("string"!=typeof S){continue;}for(T in this.ids[S]){var G=this.ids[S][T];if(!this.isTypeOfDD(G)){continue;}if(G.isTarget&&!G.isLocked()&&G!=c){if(this.isOverTarget(Q,G,this.mode,V)){D[S]=true;if(M){d.dropEvts.push(G);}else{if(!I[G.id]){d.enterEvts.push(G);}else{d.overEvts.push(G);}this.dragOvers[G.id]=G;}}}}}this.interactionInfo={out:d.outEvts,enter:d.enterEvts,over:d.overEvts,drop:d.dropEvts,point:Q,draggedRegion:V,sourceRegion:this.locationCache[c.id],validDrop:M};for(var C in D){R.push(C);}if(M&&!d.dropEvts.length){this.interactionInfo.validDrop=false;if(c.events.invalidDrop){c.onInvalidDrop(W);c.fireEvent("invalidDropEvent",{e:W});}}for(T=0;T2000){}else{setTimeout(C._addListeners,10);if(document&&document.body){C._timeoutCount+=1;}}}},handleWasClicked:function(C,E){if(this.isHandle(E,C.id)){return true;}else{var D=C.parentNode;while(D){if(this.isHandle(E,D.id)){return true;}else{D=D.parentNode;}}}return false;}};}();YAHOO.util.DDM=YAHOO.util.DragDropMgr;YAHOO.util.DDM._addListeners();}(function(){var A=YAHOO.util.Event;var B=YAHOO.util.Dom;YAHOO.util.DragDrop=function(E,C,D){if(E){this.init(E,C,D);}};YAHOO.util.DragDrop.prototype={events:null,on:function(){this.subscribe.apply(this,arguments);},id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isTarget:true,padding:null,dragOnly:false,useShim:false,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,deltaX:0,deltaY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,cursorIsOver:false,overlap:null,b4StartDrag:function(C,D){},startDrag:function(C,D){},b4Drag:function(C){},onDrag:function(C){},onDragEnter:function(C,D){},b4DragOver:function(C){},onDragOver:function(C,D){},b4DragOut:function(C){},onDragOut:function(C,D){},b4DragDrop:function(C){},onDragDrop:function(C,D){},onInvalidDrop:function(C){},b4EndDrag:function(C){},endDrag:function(C){},b4MouseDown:function(C){},onMouseDown:function(C){},onMouseUp:function(C){},onAvailable:function(){},getEl:function(){if(!this._domRef){this._domRef=B.get(this.id); +}return this._domRef;},getDragEl:function(){return B.get(this.dragElId);},init:function(F,C,D){this.initTarget(F,C,D);A.on(this._domRef||this.id,"mousedown",this.handleMouseDown,this,true);for(var E in this.events){this.createEvent(E+"Event");}},initTarget:function(E,C,D){this.config=D||{};this.events={};this.DDM=YAHOO.util.DDM;this.groups={};if(typeof E!=="string"){this._domRef=E;E=B.generateId(E);}this.id=E;this.addToGroup((C)?C:"default");this.handleElId=E;A.onAvailable(E,this.handleOnAvailable,this,true);this.setDragElId(E);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();},applyConfig:function(){this.events={mouseDown:true,b4MouseDown:true,mouseUp:true,b4StartDrag:true,startDrag:true,b4EndDrag:true,endDrag:true,drag:true,b4Drag:true,invalidDrop:true,b4DragOut:true,dragOut:true,dragEnter:true,b4DragOver:true,dragOver:true,b4DragDrop:true,dragDrop:true};if(this.config.events){for(var C in this.config.events){if(this.config.events[C]===false){this.events[C]=false;}}}this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false);this.dragOnly=((this.config.dragOnly===true)?true:false);this.useShim=((this.config.useShim===true)?true:false);},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable();},setPadding:function(E,C,F,D){if(!C&&0!==C){this.padding=[E,E,E,E];}else{if(!F&&0!==F){this.padding=[E,C,E,C];}else{this.padding=[E,C,F,D];}}},setInitPosition:function(F,E){var G=this.getEl();if(!this.DDM.verifyEl(G)){if(G&&G.style&&(G.style.display=="none")){}else{}return;}var D=F||0;var C=E||0;var H=B.getXY(G);this.initPageX=H[0]-D;this.initPageY=H[1]-C;this.lastPageX=H[0];this.lastPageY=H[1];this.setStartPosition(H);},setStartPosition:function(D){var C=D||B.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=C[0];this.startPageY=C[1];},addToGroup:function(C){this.groups[C]=true;this.DDM.regDragDrop(this,C);},removeFromGroup:function(C){if(this.groups[C]){delete this.groups[C];}this.DDM.removeDDFromGroup(this,C);},setDragElId:function(C){this.dragElId=C;},setHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.handleElId=C;this.DDM.regHandle(this.id,C);},setOuterHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}A.on(C,"mousedown",this.handleMouseDown,this,true);this.setHandleElId(C);this.hasOuterHandles=true;},unreg:function(){A.removeListener(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this);},isLocked:function(){return(this.DDM.isLocked()||this.locked);},handleMouseDown:function(J,I){var D=J.which||J.button;if(this.primaryButtonOnly&&D>1){return;}if(this.isLocked()){return;}var C=this.b4MouseDown(J),F=true;if(this.events.b4MouseDown){F=this.fireEvent("b4MouseDownEvent",J);}var E=this.onMouseDown(J),H=true;if(this.events.mouseDown){if(E===false){H=false;}else{H=this.fireEvent("mouseDownEvent",J);}}if((C===false)||(E===false)||(F===false)||(H===false)){return;}this.DDM.refreshCache(this.groups);var G=new YAHOO.util.Point(A.getPageX(J),A.getPageY(J));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(G,this)){}else{if(this.clickValidator(J)){this.setStartPosition();this.DDM.handleMouseDown(J,this);this.DDM.stopEvent(J);}else{}}},clickValidator:function(D){var C=YAHOO.util.Event.getTarget(D);return(this.isValidHandleChild(C)&&(this.id==this.handleElId||this.DDM.handleWasClicked(C,this.id)));},getTargetCoord:function(E,D){var C=E-this.deltaX;var F=D-this.deltaY;if(this.constrainX){if(Cthis.maxX){C=this.maxX;}}if(this.constrainY){if(Fthis.maxY){F=this.maxY;}}C=this.getTick(C,this.xTicks);F=this.getTick(F,this.yTicks);return{x:C,y:F};},addInvalidHandleType:function(C){var D=C.toUpperCase();this.invalidHandleTypes[D]=D;},addInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.invalidHandleIds[C]=C;},addInvalidHandleClass:function(C){this.invalidHandleClasses.push(C);},removeInvalidHandleType:function(C){var D=C.toUpperCase();delete this.invalidHandleTypes[D];},removeInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}delete this.invalidHandleIds[C];},removeInvalidHandleClass:function(D){for(var E=0,C=this.invalidHandleClasses.length;E=this.minX;D=D-C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}for(D=this.initPageX;D<=this.maxX;D=D+C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}this.xTicks.sort(this.DDM.numericSort);},setYTicks:function(F,C){this.yTicks=[];this.yTickSize=C;var E={};for(var D=this.initPageY;D>=this.minY;D=D-C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}for(D=this.initPageY;D<=this.maxY;D=D+C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}this.yTicks.sort(this.DDM.numericSort);},setXConstraint:function(E,D,C){this.leftConstraint=parseInt(E,10);this.rightConstraint=parseInt(D,10);this.minX=this.initPageX-this.leftConstraint;this.maxX=this.initPageX+this.rightConstraint;if(C){this.setXTicks(this.initPageX,C);}this.constrainX=true;},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks();},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0;},setYConstraint:function(C,E,D){this.topConstraint=parseInt(C,10);this.bottomConstraint=parseInt(E,10);this.minY=this.initPageY-this.topConstraint;this.maxY=this.initPageY+this.bottomConstraint; +if(D){this.setYTicks(this.initPageY,D);}this.constrainY=true;},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var D=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var C=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(D,C);}else{this.setInitPosition();}if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize);}if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize);}},getTick:function(I,F){if(!F){return I;}else{if(F[0]>=I){return F[0];}else{for(var D=0,C=F.length;D=I){var H=I-F[D];var G=F[E]-I;return(G>H)?F[D]:F[E];}}return F[F.length-1];}}},toString:function(){return("DragDrop "+this.id);}};YAHOO.augment(YAHOO.util.DragDrop,YAHOO.util.EventProvider);})();YAHOO.util.DD=function(C,A,B){if(C){this.init(C,A,B);}};YAHOO.extend(YAHOO.util.DD,YAHOO.util.DragDrop,{scroll:true,autoOffset:function(C,B){var A=C-this.startPageX;var D=B-this.startPageY;this.setDelta(A,D);},setDelta:function(B,A){this.deltaX=B;this.deltaY=A;},setDragElPos:function(C,B){var A=this.getDragEl();this.alignElWithMouse(A,C,B);},alignElWithMouse:function(C,G,F){var E=this.getTargetCoord(G,F);if(!this.deltaSetXY){var H=[E.x,E.y];YAHOO.util.Dom.setXY(C,H);var D=parseInt(YAHOO.util.Dom.getStyle(C,"left"),10);var B=parseInt(YAHOO.util.Dom.getStyle(C,"top"),10);this.deltaSetXY=[D-E.x,B-E.y];}else{YAHOO.util.Dom.setStyle(C,"left",(E.x+this.deltaSetXY[0])+"px");YAHOO.util.Dom.setStyle(C,"top",(E.y+this.deltaSetXY[1])+"px");}this.cachePosition(E.x,E.y);var A=this;setTimeout(function(){A.autoScroll.call(A,E.x,E.y,C.offsetHeight,C.offsetWidth);},0);},cachePosition:function(B,A){if(B){this.lastPageX=B;this.lastPageY=A;}else{var C=YAHOO.util.Dom.getXY(this.getEl());this.lastPageX=C[0];this.lastPageY=C[1];}},autoScroll:function(J,I,E,K){if(this.scroll){var L=this.DDM.getClientHeight();var B=this.DDM.getClientWidth();var N=this.DDM.getScrollTop();var D=this.DDM.getScrollLeft();var H=E+I;var M=K+J;var G=(L+N-I-this.deltaY);var F=(B+D-J-this.deltaX);var C=40;var A=(document.all)?80:30;if(H>L&&G0&&I-NB&&F0&&J-D":">",'"':""","'":"'","/":"/","`":"`"},d=["toString","valueOf"],e={isArray:function(j){return a.toString.apply(j)===c;},isBoolean:function(j){return typeof j==="boolean";},isFunction:function(j){return(typeof j==="function")||a.toString.apply(j)===h;},isNull:function(j){return j===null;},isNumber:function(j){return typeof j==="number"&&isFinite(j);},isObject:function(j){return(j&&(typeof j==="object"||f.isFunction(j)))||false;},isString:function(j){return typeof j==="string";},isUndefined:function(j){return typeof j==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(l,k){var j,n,m;for(j=0;j"'\/`]/g,function(k){return g[k];});},extend:function(m,n,l){if(!n||!m){throw new Error("extend failed, please check that "+"all dependencies are included.");}var k=function(){},j;k.prototype=n.prototype;m.prototype=new k();m.prototype.constructor=m;m.superclass=n.prototype;if(n.prototype.constructor==a.constructor){n.prototype.constructor=n;}if(l){for(j in l){if(f.hasOwnProperty(l,j)){m.prototype[j]=l[j];}}f._IEEnumFix(m.prototype,l);}},augmentObject:function(n,m){if(!m||!n){throw new Error("Absorb failed, verify dependencies.");}var j=arguments,l,o,k=j[2];if(k&&k!==true){for(l=2;l0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}if(r.length>1){r.pop();}r.push("]");}else{r.push("{");for(l in j){if(f.hasOwnProperty(j,l)){r.push(l+m);if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}}if(r.length>1){r.pop();}r.push("}");}return r.join("");},substitute:function(x,y,E,l){var D,C,B,G,t,u,F=[],p,z=x.length,A="dump",r=" ",q="{",m="}",n,w;for(;;){D=x.lastIndexOf(q,z);if(D<0){break;}C=x.indexOf(m,D);if(D+1>C){break;}p=x.substring(D+1,C);G=p;u=null;B=G.indexOf(r);if(B>-1){u=G.substring(B+1);G=G.substring(0,B);}t=y[G];if(E){t=E(G,t,u);}if(f.isObject(t)){if(f.isArray(t)){t=f.dump(t,parseInt(u,10));}else{u=u||"";n=u.indexOf(A);if(n>-1){u=u.substring(4);}w=t.toString();if(w===i||n>-1){t=f.dump(t,parseInt(u,10));}else{t=w;}}}else{if(!f.isString(t)&&!f.isNumber(t)){t="~-"+F.length+"-~";F[F.length]=p;}}x=x.substring(0,D)+t+x.substring(C+1);if(l===false){z=D-1;}}for(D=F.length-1;D>=0;D=D-1){x=x.replace(new RegExp("~-"+D+"-~"),"{"+F[D]+"}","g");}return x;},trim:function(j){try{return j.replace(/^\s+|\s+$/g,"");}catch(k){return j; +}},merge:function(){var n={},k=arguments,j=k.length,m;for(m=0;m-1;}}else{}return G;},addClass:function(W,G){return e.Dom.batch(W,e.Dom._addClass,G);},_addClass:function(X,W){var G=false,Y;if(X&&W){Y=e.Dom._getAttribute(X,f)||i;if(!e.Dom._hasClass(X,W)){e.Dom.setAttribute(X,f,a(Y+b+W));G=true;}}else{}return G;},removeClass:function(W,G){return e.Dom.batch(W,e.Dom._removeClass,G);},_removeClass:function(Y,X){var W=false,aa,Z,G;if(Y&&X){aa=e.Dom._getAttribute(Y,f)||i;e.Dom.setAttribute(Y,f,aa.replace(e.Dom._getClassRegex(X),i));Z=e.Dom._getAttribute(Y,f);if(aa!==Z){e.Dom.setAttribute(Y,f,a(Z));W=true;if(e.Dom._getAttribute(Y,f)===""){G=(Y.hasAttribute&&Y.hasAttribute(E))?E:f;Y.removeAttribute(G);}}}else{}return W;},replaceClass:function(X,W,G){return e.Dom.batch(X,e.Dom._replaceClass,{from:W,to:G});},_replaceClass:function(Y,X){var W,ab,aa,G=false,Z;if(Y&&X){ab=X.from;aa=X.to;if(!aa){G=false;}else{if(!ab){G=e.Dom._addClass(Y,X.to);}else{if(ab!==aa){Z=e.Dom._getAttribute(Y,f)||i;W=(b+Z.replace(e.Dom._getClassRegex(ab),b+aa).replace(/\s+/g,b)).split(e.Dom._getClassRegex(aa));W.splice(1,0,b+aa);e.Dom.setAttribute(Y,f,a(W.join(i)));G=true;}}}}else{}return G;},generateId:function(G,X){X=X||"yui-gen";var W=function(Y){if(Y&&Y.id){return Y.id;}var Z=X+YAHOO.env._id_counter++; +if(Y){if(Y[C]&&Y[C].getElementById(Z)){return e.Dom.generateId(Y,Z+X);}Y.id=Z;}return Z;};return e.Dom.batch(G,W,e.Dom,true)||W.apply(e.Dom,arguments);},isAncestor:function(W,X){W=e.Dom.get(W);X=e.Dom.get(X);var G=false;if((W&&X)&&(W[K]&&X[K])){if(W.contains&&W!==X){G=W.contains(X);}else{if(W.compareDocumentPosition){G=!!(W.compareDocumentPosition(X)&16);}}}else{}return G;},inDocument:function(G,W){return e.Dom._inDoc(e.Dom.get(G),W);},_inDoc:function(W,X){var G=false;if(W&&W[c]){X=X||W[C];G=e.Dom.isAncestor(X[U],W);}else{}return G;},getElementsBy:function(W,af,ab,ad,X,ac,ae){af=af||"*";ab=(ab)?e.Dom.get(ab):null||j;var aa=(ae)?null:[],G;if(ab){G=ab.getElementsByTagName(af);for(var Y=0,Z=G.length;Y=8){e.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(d,e,a,c){this.top=d;this.y=d;this[1]=d;this.right=e;this.bottom=a;this.left=c;this.x=c;this[0]=c;this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(a){return(a.left>=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(f){var d=Math.max(this.top,f.top),e=Math.min(this.right,f.right),a=Math.min(this.bottom,f.bottom),c=Math.max(this.left,f.left); +if(a>=d&&e>=c){return new YAHOO.util.Region(d,e,a,c);}else{return null;}};YAHOO.util.Region.prototype.union=function(f){var d=Math.min(this.top,f.top),e=Math.max(this.right,f.right),a=Math.max(this.bottom,f.bottom),c=Math.min(this.left,f.left);return new YAHOO.util.Region(d,e,a,c);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(e){var g=YAHOO.util.Dom.getXY(e),d=g[1],f=g[0]+e.offsetWidth,a=g[1]+e.offsetHeight,c=g[0];return new YAHOO.util.Region(d,f,a,c);};YAHOO.util.Point=function(a,b){if(YAHOO.lang.isArray(a)){b=a[1];a=a[0];}YAHOO.util.Point.superclass.constructor.call(this,b,a,b,a);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var b=YAHOO.util,a="clientTop",f="clientLeft",j="parentNode",k="right",w="hasLayout",i="px",u="opacity",l="auto",d="borderLeftWidth",g="borderTopWidth",p="borderRightWidth",v="borderBottomWidth",s="visible",q="transparent",n="height",e="width",h="style",t="currentStyle",r=/^width|height$/,o=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,m={get:function(x,z){var y="",A=x[t][z];if(z===u){y=b.Dom.getStyle(x,u);}else{if(!A||(A.indexOf&&A.indexOf(i)>-1)){y=A;}else{if(b.Dom.IE_COMPUTED[z]){y=b.Dom.IE_COMPUTED[z](x,z);}else{if(o.test(A)){y=b.Dom.IE.ComputedStyle.getPixel(x,z);}else{y=A;}}}}return y;},getOffset:function(z,E){var B=z[t][E],x=E.charAt(0).toUpperCase()+E.substr(1),C="offset"+x,y="pixel"+x,A="",D;if(B==l){D=z[C];if(D===undefined){A=0;}A=D;if(r.test(E)){z[h][E]=D;if(z[C]>D){A=D-(z[C]-D);}z[h][E]=l;}}else{if(!z[h][y]&&!z[h][E]){z[h][E]=B;}A=z[h][y];}return A+i;},getBorderWidth:function(x,z){var y=null;if(!x[t][w]){x[h].zoom=1;}switch(z){case g:y=x[a];break;case v:y=x.offsetHeight-x.clientHeight-x[a];break;case d:y=x[f];break;case p:y=x.offsetWidth-x.clientWidth-x[f];break;}return y+i;},getPixel:function(y,x){var A=null,B=y[t][k],z=y[t][x];y[h][k]=z;A=y[h].pixelRight;y[h][k]=B;return A+i;},getMargin:function(y,x){var z;if(y[t][x]==l){z=0+i;}else{z=b.Dom.IE.ComputedStyle.getPixel(y,x);}return z;},getVisibility:function(y,x){var z;while((z=y[t])&&z[x]=="inherit"){y=y[j];}return(z)?z[x]:s;},getColor:function(y,x){return b.Dom.Color.toRGB(y[t][x])||q;},getBorderColor:function(y,x){var z=y[t],A=z[x]||z.color;return b.Dom.Color.toRGB(b.Dom.Color.toHex(A));}},c={};c.top=c.right=c.bottom=c.left=c[e]=c[n]=m.getOffset;c.color=m.getColor;c[g]=c[p]=c[v]=c[d]=m.getBorderWidth;c.marginTop=c.marginRight=c.marginBottom=c.marginLeft=m.getMargin;c.visibility=m.getVisibility;c.borderColor=c.borderTopColor=c.borderRightColor=c.borderBottomColor=c.borderLeftColor=m.getBorderColor;b.Dom.IE_COMPUTED=c;b.Dom.IE_ComputedStyle=m;})();(function(){var c="toString",a=parseInt,b=RegExp,d=YAHOO.util;d.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(e){if(!d.Dom.Color.re_RGB.test(e)){e=d.Dom.Color.toHex(e);}if(d.Dom.Color.re_hex.exec(e)){e="rgb("+[a(b.$1,16),a(b.$2,16),a(b.$3,16)].join(", ")+")";}return e;},toHex:function(f){f=d.Dom.Color.KEYWORDS[f]||f;if(d.Dom.Color.re_RGB.exec(f)){f=[Number(b.$1).toString(16),Number(b.$2).toString(16),Number(b.$3).toString(16)];for(var e=0;e0){i=c[0];}try{b=g.fn.call(f,i,g.obj);}catch(h){this.lastError=h;if(a){throw h;}}}else{try{b=g.fn.call(f,this.type,c,g.obj);}catch(d){this.lastError=d;if(a){throw d;}}}return b;},unsubscribeAll:function(){var a=this.subscribers.length,b;for(b=a-1;b>-1;b--){this._delete(b);}this.subscribers=[];return a;},_delete:function(a){var b=this.subscribers[a];if(b){delete b.fn;delete b.obj;}this.subscribers.splice(a,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(a,b,c){this.fn=a;this.obj=YAHOO.lang.isUndefined(b)?null:b;this.overrideContext=c;};YAHOO.util.Subscriber.prototype.getScope=function(a){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return a;};YAHOO.util.Subscriber.prototype.contains=function(a,b){if(b){return(this.fn==a&&this.obj==b);}else{return(this.fn==a);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var g=false,h=[],j=[],a=0,e=[],b=0,c={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},d=YAHOO.env.ua.ie,f="focusin",i="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:d,_interval:null,_dri:null,_specialTypes:{focusin:(d?"focusin":"focus"),focusout:(d?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(q,m,o,p,n){var k=(YAHOO.lang.isString(q))?[q]:q;for(var l=0;l-1;m--){s=(this.removeListener(l[m],k,r)&&s);}return s;}}if(!r||!r.call){return this.purgeElement(l,false,k);}if("unload"==k){for(m=j.length-1;m>-1;m--){u=j[m];if(u&&u[0]==l&&u[1]==k&&u[2]==r){j.splice(m,1);return true;}}return false;}var n=null;var o=arguments[3];if("undefined"===typeof o){o=this._getCacheIndex(h,l,k,r);}if(o>=0){n=h[o];}if(!l||!n){return false;}var t=n[this.CAPTURE]===true?true:false;try{this._simpleRemove(l,k,n[this.WFN],t);}catch(q){this.lastError=q;return false;}delete h[o][this.WFN];delete h[o][this.FN];h.splice(o,1);return true;},getTarget:function(m,l){var k=m.target||m.srcElement;return this.resolveTextNode(k);},resolveTextNode:function(l){try{if(l&&3==l.nodeType){return l.parentNode;}}catch(k){return null;}return l;},getPageX:function(l){var k=l.pageX;if(!k&&0!==k){k=l.clientX||0;if(this.isIE){k+=this._getScrollLeft();}}return k;},getPageY:function(k){var l=k.pageY;if(!l&&0!==l){l=k.clientY||0;if(this.isIE){l+=this._getScrollTop();}}return l;},getXY:function(k){return[this.getPageX(k),this.getPageY(k)];},getRelatedTarget:function(l){var k=l.relatedTarget; +if(!k){if(l.type=="mouseout"){k=l.toElement;}else{if(l.type=="mouseover"){k=l.fromElement;}}}return this.resolveTextNode(k);},getTime:function(m){if(!m.time){var l=new Date().getTime();try{m.time=l;}catch(k){this.lastError=k;return l;}}return m.time;},stopEvent:function(k){this.stopPropagation(k);this.preventDefault(k);},stopPropagation:function(k){if(k.stopPropagation){k.stopPropagation();}else{k.cancelBubble=true;}},preventDefault:function(k){if(k.preventDefault){k.preventDefault();}else{k.returnValue=false;}},getEvent:function(m,k){var l=m||window.event;if(!l){var n=this.getEvent.caller;while(n){l=n.arguments[0];if(l&&Event==l.constructor){break;}n=n.caller;}}return l;},getCharCode:function(l){var k=l.keyCode||l.charCode||0;if(YAHOO.env.ua.webkit&&(k in c)){k=c[k];}return k;},_getCacheIndex:function(n,q,r,p){for(var o=0,m=n.length;o0&&e.length>0);}var p=[];var r=function(t,u){var s=t;if(u.overrideContext){if(u.overrideContext===true){s=u.obj;}else{s=u.overrideContext;}}u.fn.call(s,u.obj);};var l,k,o,n,m=[];for(l=0,k=e.length;l-1;l--){o=e[l];if(!o||!o.id){e.splice(l,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(p,q,s){var n=(YAHOO.lang.isString(p))?this.getEl(p):p;var r=this.getListeners(n,s),o,k;if(r){for(o=r.length-1;o>-1;o--){var m=r[o];this.removeListener(n,m.type,m.fn);}}if(q&&n&&n.childNodes){for(o=0,k=n.childNodes.length;o-1;o--){n=h[o];if(n){try{m.removeListener(n[m.EL],n[m.TYPE],n[m.FN],o);}catch(v){}}}n=null;}try{m._simpleRemove(window,"unload",m._unload);m._simpleRemove(window,"load",m._load);}catch(u){}},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var k=document.documentElement,l=document.body;if(k&&(k.scrollTop||k.scrollLeft)){return[k.scrollTop,k.scrollLeft];}else{if(l){return[l.scrollTop,l.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(m,n,l,k){m.addEventListener(n,l,(k));};}else{if(window.attachEvent){return function(m,n,l,k){m.attachEvent("on"+n,l);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(m,n,l,k){m.removeEventListener(n,l,(k));};}else{if(window.detachEvent){return function(l,m,k){l.detachEvent("on"+m,k);};}else{return function(){};}}}()};}();(function(){var a=YAHOO.util.Event;a.on=a.addListener;a.onFocus=a.addFocusListener;a.onBlur=a.addBlurListener; +/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ +if(a.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;a._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var b=document.createElement("p");a._dri=setInterval(function(){try{b.doScroll("left");clearInterval(a._dri);a._dri=null;a._ready();b=null;}catch(c){}},a.POLL_INTERVAL);}}else{if(a.webkit&&a.webkit<525){a._dri=setInterval(function(){var c=document.readyState;if("loaded"==c||"complete"==c){clearInterval(a._dri);a._dri=null;a._ready();}},a.POLL_INTERVAL);}else{a._simpleAdd(document,"DOMContentLoaded",a._ready);}}a._simpleAdd(window,"load",a._load);a._simpleAdd(window,"unload",a._unload);a._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(a,c,f,e){this.__yui_events=this.__yui_events||{};var d=this.__yui_events[a];if(d){d.subscribe(c,f,e);}else{this.__yui_subscribers=this.__yui_subscribers||{};var b=this.__yui_subscribers;if(!b[a]){b[a]=[];}b[a].push({fn:c,obj:f,overrideContext:e});}},unsubscribe:function(c,e,g){this.__yui_events=this.__yui_events||{};var a=this.__yui_events;if(c){var f=a[c];if(f){return f.unsubscribe(e,g);}}else{var b=true;for(var d in a){if(YAHOO.lang.hasOwnProperty(a,d)){b=b&&a[d].unsubscribe(e,g); +}}return b;}return false;},unsubscribeAll:function(a){return this.unsubscribe(a);},createEvent:function(b,g){this.__yui_events=this.__yui_events||{};var e=g||{},d=this.__yui_events,f;if(d[b]){}else{f=new YAHOO.util.CustomEvent(b,e.scope||this,e.silent,YAHOO.util.CustomEvent.FLAT,e.fireOnce);d[b]=f;if(e.onSubscribeCallback){f.subscribeEvent.subscribe(e.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var a=this.__yui_subscribers[b];if(a){for(var c=0;c + * YAHOO.env.getVersion for the description of the version data structure. + * @property listener + * @type Function + * @static + * @default undefined + */ + +/** + * Set to true if the library will be dynamically loaded after window.onload. + * Defaults to false + * @property injecting + * @type boolean + * @static + * @default undefined + */ + +/** + * Instructs the yuiloader component to dynamically load yui components and + * their dependencies. See the yuiloader documentation for more information + * about dynamic loading + * @property load + * @static + * @default undefined + * @see yuiloader + */ + +/** + * Forces the use of the supplied locale where applicable in the library + * @property locale + * @type string + * @static + * @default undefined + */ + +if (typeof YAHOO == "undefined" || !YAHOO) { + /** + * The YAHOO global namespace object. If YAHOO is already defined, the + * existing YAHOO object will not be overwritten so that defined + * namespaces are preserved. + * @class YAHOO + * @static + */ + var YAHOO = {}; +} + +/** + * Returns the namespace specified and creates it if it doesn't exist + *
    + * YAHOO.namespace("property.package");
    + * YAHOO.namespace("YAHOO.property.package");
    + * 
    + * Either of the above would create YAHOO.property, then + * YAHOO.property.package + * + * Be careful when naming packages. Reserved words may work in some browsers + * and not others. For instance, the following will fail in Safari: + *
    + * YAHOO.namespace("really.long.nested.namespace");
    + * 
    + * This fails because "long" is a future reserved word in ECMAScript + * + * For implementation code that uses YUI, do not create your components + * in the namespaces defined by YUI ( + * YAHOO.util, + * YAHOO.widget, + * YAHOO.lang, + * YAHOO.tool, + * YAHOO.example, + * YAHOO.env) -- create your own namespace (e.g., 'companyname'). + * + * @method namespace + * @static + * @param {String*} arguments 1-n namespaces to create + * @return {Object} A reference to the last namespace object created + */ +YAHOO.namespace = function() { + var a=arguments, o=null, i, j, d; + for (i=0; i + *
    name:
    The name of the module
    + *
    version:
    The version in use
    + *
    build:
    The build number in use
    + *
    versions:
    All versions that were registered
    + *
    builds:
    All builds that were registered.
    + *
    mainClass:
    An object that was was stamped with the + * current version and build. If + * mainClass.VERSION != version or mainClass.BUILD != build, + * multiple versions of pieces of the library have been + * loaded, potentially causing issues.
    + * + * + * @method getVersion + * @static + * @param {String} name the name of the module (event, slider, etc) + * @return {Object} The version info + */ +YAHOO.env.getVersion = function(name) { + return YAHOO.env.modules[name] || null; +}; + +/** + * Do not fork for a browser if it can be avoided. Use feature detection when + * you can. Use the user agent as a last resort. YAHOO.env.ua stores a version + * number for the browser engine, 0 otherwise. This value may or may not map + * to the version number of the browser using the engine. The value is + * presented as a float so that it can easily be used for boolean evaluation + * as well as for looking for a particular range of versions. Because of this, + * some of the granularity of the version info may be lost (e.g., Gecko 1.8.0.9 + * reports 1.8). + * @class YAHOO.env.ua + * @static + */ + +/** + * parses a user agent string (or looks for one in navigator to parse if + * not supplied). + * @method parseUA + * @since 2.9.0 + * @static + */ +YAHOO.env.parseUA = function(agent) { + + var numberify = function(s) { + var c = 0; + return parseFloat(s.replace(/\./g, function() { + return (c++ == 1) ? '' : '.'; + })); + }, + + nav = navigator, + + o = { + + /** + * Internet Explorer version number or 0. Example: 6 + * @property ie + * @type float + * @static + */ + ie: 0, + + /** + * Opera version number or 0. Example: 9.2 + * @property opera + * @type float + * @static + */ + opera: 0, + + /** + * Gecko engine revision number. Will evaluate to 1 if Gecko + * is detected but the revision could not be found. Other browsers + * will be 0. Example: 1.8 + *
    +         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
    +         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
    +         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
    +         * Firefox 3.0   <-- 1.9
    +         * Firefox 3.5   <-- 1.91
    +         * 
    + * @property gecko + * @type float + * @static + */ + gecko: 0, + + /** + * AppleWebKit version. KHTML browsers that are not WebKit browsers + * will evaluate to 1, other browsers 0. Example: 418.9 + *
    +         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
    +         *                                   latest available for Mac OSX 10.3.
    +         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
    +         * Safari 2.0.4:         418     <-- preventDefault fixed
    +         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
    +         *                                   different versions of webkit
    +         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
    +         *                                   updated, but not updated
    +         *                                   to the latest patch.
    +         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
    +         * SVG and many major issues fixed).
    +         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
    +         * update from 2.x via the 10.4.11 OS patch.
    +         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
    +         *                                   yahoo.com user agent hack removed.
    +         * 
    + * http://en.wikipedia.org/wiki/Safari_version_history + * @property webkit + * @type float + * @static + */ + webkit: 0, + + /** + * Chrome will be detected as webkit, but this property will also + * be populated with the Chrome version number + * @property chrome + * @type float + * @static + */ + chrome: 0, + + /** + * The mobile property will be set to a string containing any relevant + * user agent information when a modern mobile browser is detected. + * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series + * devices with the WebKit-based browser, and Opera Mini. + * @property mobile + * @type string + * @static + */ + mobile: null, + + /** + * Adobe AIR version number or 0. Only populated if webkit is detected. + * Example: 1.0 + * @property air + * @type float + */ + air: 0, + /** + * Detects Apple iPad's OS version + * @property ipad + * @type float + * @static + */ + ipad: 0, + /** + * Detects Apple iPhone's OS version + * @property iphone + * @type float + * @static + */ + iphone: 0, + /** + * Detects Apples iPod's OS version + * @property ipod + * @type float + * @static + */ + ipod: 0, + /** + * General truthy check for iPad, iPhone or iPod + * @property ios + * @type float + * @static + */ + ios: null, + /** + * Detects Googles Android OS version + * @property android + * @type float + * @static + */ + android: 0, + /** + * Detects Palms WebOS version + * @property webos + * @type float + * @static + */ + webos: 0, + + /** + * Google Caja version number or 0. + * @property caja + * @type float + */ + caja: nav && nav.cajaVersion, + + /** + * Set to true if the page appears to be in SSL + * @property secure + * @type boolean + * @static + */ + secure: false, + + /** + * The operating system. Currently only detecting windows or macintosh + * @property os + * @type string + * @static + */ + os: null + + }, + + ua = agent || (navigator && navigator.userAgent), + + loc = window && window.location, + + href = loc && loc.href, + + m; + + o.secure = href && (href.toLowerCase().indexOf("https") === 0); + + if (ua) { + + if ((/windows|win32/i).test(ua)) { + o.os = 'windows'; + } else if ((/macintosh/i).test(ua)) { + o.os = 'macintosh'; + } else if ((/rhino/i).test(ua)) { + o.os = 'rhino'; + } + + // Modern KHTML browsers should qualify as Safari X-Grade + if ((/KHTML/).test(ua)) { + o.webkit = 1; + } + // Modern WebKit browsers are at least X-Grade + m = ua.match(/AppleWebKit\/([^\s]*)/); + if (m && m[1]) { + o.webkit = numberify(m[1]); + + // Mobile browser check + if (/ Mobile\//.test(ua)) { + o.mobile = 'Apple'; // iPhone or iPod Touch + + m = ua.match(/OS ([^\s]*)/); + if (m && m[1]) { + m = numberify(m[1].replace('_', '.')); + } + o.ios = m; + o.ipad = o.ipod = o.iphone = 0; + + m = ua.match(/iPad|iPod|iPhone/); + if (m && m[0]) { + o[m[0].toLowerCase()] = o.ios; + } + } else { + m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/); + if (m) { + // Nokia N-series, Android, webOS, ex: NokiaN95 + o.mobile = m[0]; + } + if (/webOS/.test(ua)) { + o.mobile = 'WebOS'; + m = ua.match(/webOS\/([^\s]*);/); + if (m && m[1]) { + o.webos = numberify(m[1]); + } + } + if (/ Android/.test(ua)) { + o.mobile = 'Android'; + m = ua.match(/Android ([^\s]*);/); + if (m && m[1]) { + o.android = numberify(m[1]); + } + + } + } + + m = ua.match(/Chrome\/([^\s]*)/); + if (m && m[1]) { + o.chrome = numberify(m[1]); // Chrome + } else { + m = ua.match(/AdobeAIR\/([^\s]*)/); + if (m) { + o.air = m[0]; // Adobe AIR 1.0 or better + } + } + } + + if (!o.webkit) { // not webkit +// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) + m = ua.match(/Opera[\s\/]([^\s]*)/); + if (m && m[1]) { + o.opera = numberify(m[1]); + m = ua.match(/Version\/([^\s]*)/); + if (m && m[1]) { + o.opera = numberify(m[1]); // opera 10+ + } + m = ua.match(/Opera Mini[^;]*/); + if (m) { + o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 + } + } else { // not opera or webkit + m = ua.match(/MSIE\s([^;]*)/); + if (m && m[1]) { + o.ie = numberify(m[1]); + } else { // not opera, webkit, or ie + m = ua.match(/Gecko\/([^\s]*)/); + if (m) { + o.gecko = 1; // Gecko detected, look for revision + m = ua.match(/rv:([^\s\)]*)/); + if (m && m[1]) { + o.gecko = numberify(m[1]); + } + } + } + } + } + } + + return o; +}; + +YAHOO.env.ua = YAHOO.env.parseUA(); + +/* + * Initializes the global by creating the default namespaces and applying + * any new configuration information that is detected. This is the setup + * for env. + * @method init + * @static + * @private + */ +(function() { + YAHOO.namespace("util", "widget", "example"); + /*global YAHOO_config*/ + if ("undefined" !== typeof YAHOO_config) { + var l=YAHOO_config.listener, ls=YAHOO.env.listeners,unique=true, i; + if (l) { + // if YAHOO is loaded multiple times we need to check to see if + // this is a new config object. If it is, add the new component + // load listener to the stack + for (i=0; i': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`' + }, + + // ADD = ["toString", "valueOf", "hasOwnProperty"], + ADD = ["toString", "valueOf"], + + OB = { + + /** + * Determines wheather or not the provided object is an array. + * @method isArray + * @param {any} o The object being testing + * @return {boolean} the result + */ + isArray: function(o) { + return OP.toString.apply(o) === ARRAY_TOSTRING; + }, + + /** + * Determines whether or not the provided object is a boolean + * @method isBoolean + * @param {any} o The object being testing + * @return {boolean} the result + */ + isBoolean: function(o) { + return typeof o === 'boolean'; + }, + + /** + * Determines whether or not the provided object is a function. + * Note: Internet Explorer thinks certain functions are objects: + * + * var obj = document.createElement("object"); + * YAHOO.lang.isFunction(obj.getAttribute) // reports false in IE + * + * var input = document.createElement("input"); // append to body + * YAHOO.lang.isFunction(input.focus) // reports false in IE + * + * You will have to implement additional tests if these functions + * matter to you. + * + * @method isFunction + * @param {any} o The object being testing + * @return {boolean} the result + */ + isFunction: function(o) { + return (typeof o === 'function') || OP.toString.apply(o) === FUNCTION_TOSTRING; + }, + + /** + * Determines whether or not the provided object is null + * @method isNull + * @param {any} o The object being testing + * @return {boolean} the result + */ + isNull: function(o) { + return o === null; + }, + + /** + * Determines whether or not the provided object is a legal number + * @method isNumber + * @param {any} o The object being testing + * @return {boolean} the result + */ + isNumber: function(o) { + return typeof o === 'number' && isFinite(o); + }, + + /** + * Determines whether or not the provided object is of type object + * or function + * @method isObject + * @param {any} o The object being testing + * @return {boolean} the result + */ + isObject: function(o) { +return (o && (typeof o === 'object' || L.isFunction(o))) || false; + }, + + /** + * Determines whether or not the provided object is a string + * @method isString + * @param {any} o The object being testing + * @return {boolean} the result + */ + isString: function(o) { + return typeof o === 'string'; + }, + + /** + * Determines whether or not the provided object is undefined + * @method isUndefined + * @param {any} o The object being testing + * @return {boolean} the result + */ + isUndefined: function(o) { + return typeof o === 'undefined'; + }, + + + /** + * IE will not enumerate native functions in a derived object even if the + * function was overridden. This is a workaround for specific functions + * we care about on the Object prototype. + * @property _IEEnumFix + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @static + * @private + */ + _IEEnumFix: (YAHOO.env.ua.ie) ? function(r, s) { + var i, fname, f; + for (i=0;i + * Returns a copy of the specified string with special HTML characters + * escaped. The following characters will be converted to their + * corresponding character entities: + * & < > " ' / ` + *

    + * + *

    + * This implementation is based on the + * OWASP + * HTML escaping recommendations. In addition to the characters + * in the OWASP recommendation, we also escape the ` + * character, since IE interprets it as an attribute delimiter when used in + * innerHTML. + *

    + * + * @method escapeHTML + * @param {String} html String to escape. + * @return {String} Escaped string. + * @static + * @since 2.9.0 + */ + escapeHTML: function (html) { + return html.replace(/[&<>"'\/`]/g, function (match) { + return HTML_CHARS[match]; + }); + }, + + /** + * Utility to set up the prototype, constructor and superclass properties to + * support an inheritance strategy that can chain constructors and methods. + * Static members will not be inherited. + * + * @method extend + * @static + * @param {Function} subc the object to modify + * @param {Function} superc the object to inherit + * @param {Object} overrides additional properties/methods to add to the + * subclass prototype. These will override the + * matching items obtained from the superclass + * if present. + */ + extend: function(subc, superc, overrides) { + if (!superc||!subc) { + throw new Error("extend failed, please check that " + + "all dependencies are included."); + } + var F = function() {}, i; + F.prototype=superc.prototype; + subc.prototype=new F(); + subc.prototype.constructor=subc; + subc.superclass=superc.prototype; + if (superc.prototype.constructor == OP.constructor) { + superc.prototype.constructor=superc; + } + + if (overrides) { + for (i in overrides) { + if (L.hasOwnProperty(overrides, i)) { + subc.prototype[i]=overrides[i]; + } + } + + L._IEEnumFix(subc.prototype, overrides); + } + }, + + /** + * Applies all properties in the supplier to the receiver if the + * receiver does not have these properties yet. Optionally, one or + * more methods/properties can be specified (as additional + * parameters). This option will overwrite the property if receiver + * has it already. If true is passed as the third parameter, all + * properties will be applied and _will_ overwrite properties in + * the receiver. + * + * @method augmentObject + * @static + * @since 2.3.0 + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @param {String*|boolean} arguments zero or more properties methods + * to augment the receiver with. If none specified, everything + * in the supplier will be used unless it would + * overwrite an existing property in the receiver. If true + * is specified as the third parameter, all properties will + * be applied and will overwrite an existing property in + * the receiver + */ + augmentObject: function(r, s) { + if (!s||!r) { + throw new Error("Absorb failed, verify dependencies."); + } + var a=arguments, i, p, overrideList=a[2]; + if (overrideList && overrideList!==true) { // only absorb the specified properties + for (i=2; i 0) ? L.dump(o[i], d-1) : OBJ); + } else { + s.push(o[i]); + } + s.push(COMMA); + } + if (s.length > 1) { + s.pop(); + } + s.push("]"); + // objects {k1 => v1, k2 => v2} + } else { + s.push("{"); + for (i in o) { + if (L.hasOwnProperty(o, i)) { + s.push(i + ARROW); + if (L.isObject(o[i])) { + s.push((d > 0) ? L.dump(o[i], d-1) : OBJ); + } else { + s.push(o[i]); + } + s.push(COMMA); + } + } + if (s.length > 1) { + s.pop(); + } + s.push("}"); + } + + return s.join(""); + }, + + /** + * Does variable substitution on a string. It scans through the string + * looking for expressions enclosed in { } braces. If an expression + * is found, it is used a key on the object. If there is a space in + * the key, the first word is used for the key and the rest is provided + * to an optional function to be used to programatically determine the + * value (the extra information might be used for this decision). If + * the value for the key in the object, or what is returned from the + * function has a string value, number value, or object value, it is + * substituted for the bracket expression and it repeats. If this + * value is an object, it uses the Object's toString() if this has + * been overridden, otherwise it does a shallow dump of the key/value + * pairs. + * + * By specifying the recurse option, the string is rescanned after + * every replacement, allowing for nested template substitutions. + * The side effect of this option is that curly braces in the + * replacement content must be encoded. + * + * @method substitute + * @since 2.3.0 + * @param s {String} The string that will be modified. + * @param o {Object} An object containing the replacement values + * @param f {Function} An optional function that can be used to + * process each match. It receives the key, + * value, and any extra metadata included with + * the key inside of the braces. + * @param recurse {boolean} default true - if not false, the replaced + * string will be rescanned so that nested substitutions are possible. + * @return {String} the substituted string + */ + substitute: function (s, o, f, recurse) { + var i, j, k, key, v, meta, saved=[], token, lidx=s.length, + DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}', + dump, objstr; + + for (;;) { + i = s.lastIndexOf(LBRACE, lidx); + if (i < 0) { + break; + } + j = s.indexOf(RBRACE, i); + if (i + 1 > j) { + break; + } + + //Extract key and meta info + token = s.substring(i + 1, j); + key = token; + meta = null; + k = key.indexOf(SPACE); + if (k > -1) { + meta = key.substring(k + 1); + key = key.substring(0, k); + } + + // lookup the value + v = o[key]; + + // if a substitution function was provided, execute it + if (f) { + v = f(key, v, meta); + } + + if (L.isObject(v)) { + if (L.isArray(v)) { + v = L.dump(v, parseInt(meta, 10)); + } else { + meta = meta || ""; + + // look for the keyword 'dump', if found force obj dump + dump = meta.indexOf(DUMP); + if (dump > -1) { + meta = meta.substring(4); + } + + objstr = v.toString(); + + // use the toString if it is not the Object toString + // and the 'dump' meta info was not found + if (objstr === OBJECT_TOSTRING || dump > -1) { + v = L.dump(v, parseInt(meta, 10)); + } else { + v = objstr; + } + } + } else if (!L.isString(v) && !L.isNumber(v)) { + // This {block} has no replace string. Save it for later. + v = "~-" + saved.length + "-~"; + saved[saved.length] = token; + + // break; + } + + s = s.substring(0, i) + v + s.substring(j + 1); + + if (recurse === false) { + lidx = i-1; + } + + } + + // restore saved {block}s + for (i=saved.length-1; i>=0; i=i-1) { + s = s.replace(new RegExp("~-" + i + "-~"), "{" + saved[i] + "}", "g"); + } + + return s; + }, + + + /** + * Returns a string without any leading or trailing whitespace. If + * the input is not a string, the input will be returned untouched. + * @method trim + * @since 2.3.0 + * @param s {string} the string to trim + * @return {string} the trimmed string + */ + trim: function(s){ + try { + return s.replace(/^\s+|\s+$/g, ""); + } catch(e) { + return s; + } + }, + + /** + * Returns a new object containing all of the properties of + * all the supplied objects. The properties from later objects + * will overwrite those in earlier objects. + * @method merge + * @since 2.3.0 + * @param arguments {Object*} the objects to merge + * @return the new merged object + */ + merge: function() { + var o={}, a=arguments, l=a.length, i; + for (i=0; i + * var A = function() {}; + * A.prototype.foo = 'foo'; + * var a = new A(); + * a.foo = 'foo'; + * alert(a.hasOwnProperty('foo')); // true + * alert(YAHOO.lang.hasOwnProperty(a, 'foo')); // false when using fallback + * + * @method hasOwnProperty + * @param {any} o The object being testing + * @param prop {string} the name of the property to test + * @return {boolean} the result + */ +L.hasOwnProperty = (OP.hasOwnProperty) ? + function(o, prop) { + return o && o.hasOwnProperty && o.hasOwnProperty(prop); + } : function(o, prop) { + return !L.isUndefined(o[prop]) && + o.constructor.prototype[prop] !== o[prop]; + }; + +// new lang wins +OB.augmentObject(L, OB, true); + +/* + * An alias for YAHOO.lang + * @class YAHOO.util.Lang + */ +YAHOO.util.Lang = L; + +/** + * Same as YAHOO.lang.augmentObject, except it only applies prototype + * properties. This is an alias for augmentProto. + * @see YAHOO.lang.augmentObject + * @method augment + * @static + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @param {String*|boolean} arguments zero or more properties methods to + * augment the receiver with. If none specified, everything + * in the supplier will be used unless it would + * overwrite an existing property in the receiver. if true + * is specified as the third parameter, all properties will + * be applied and will overwrite an existing property in + * the receiver + */ +L.augment = L.augmentProto; + +/** + * An alias for YAHOO.lang.augment + * @for YAHOO + * @method augment + * @static + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @param {String*} arguments zero or more properties methods to + * augment the receiver with. If none specified, everything + * in the supplier will be used unless it would + * overwrite an existing property in the receiver + */ +YAHOO.augment = L.augmentProto; + +/** + * An alias for YAHOO.lang.extend + * @method extend + * @static + * @param {Function} subc the object to modify + * @param {Function} superc the object to inherit + * @param {Object} overrides additional properties/methods to add to the + * subclass prototype. These will override the + * matching items obtained from the superclass if present. + */ +YAHOO.extend = L.extend; + +})(); +YAHOO.register("yahoo", YAHOO, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yahoo/yahoo-min.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yahoo/yahoo-min.js new file mode 100644 index 0000000..4f18140 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yahoo/yahoo-min.js @@ -0,0 +1,8 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var b=arguments,g=null,e,c,f;for(e=0;e":">",'"':""","'":"'","/":"/","`":"`"},d=["toString","valueOf"],e={isArray:function(j){return a.toString.apply(j)===c;},isBoolean:function(j){return typeof j==="boolean";},isFunction:function(j){return(typeof j==="function")||a.toString.apply(j)===h;},isNull:function(j){return j===null;},isNumber:function(j){return typeof j==="number"&&isFinite(j);},isObject:function(j){return(j&&(typeof j==="object"||f.isFunction(j)))||false;},isString:function(j){return typeof j==="string";},isUndefined:function(j){return typeof j==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(l,k){var j,n,m;for(j=0;j"'\/`]/g,function(k){return g[k];});},extend:function(m,n,l){if(!n||!m){throw new Error("extend failed, please check that "+"all dependencies are included.");}var k=function(){},j;k.prototype=n.prototype;m.prototype=new k();m.prototype.constructor=m;m.superclass=n.prototype;if(n.prototype.constructor==a.constructor){n.prototype.constructor=n;}if(l){for(j in l){if(f.hasOwnProperty(l,j)){m.prototype[j]=l[j];}}f._IEEnumFix(m.prototype,l);}},augmentObject:function(n,m){if(!m||!n){throw new Error("Absorb failed, verify dependencies.");}var j=arguments,l,o,k=j[2];if(k&&k!==true){for(l=2;l0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}if(r.length>1){r.pop();}r.push("]");}else{r.push("{");for(l in j){if(f.hasOwnProperty(j,l)){r.push(l+m);if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}}if(r.length>1){r.pop();}r.push("}");}return r.join("");},substitute:function(x,y,E,l){var D,C,B,G,t,u,F=[],p,z=x.length,A="dump",r=" ",q="{",m="}",n,w;for(;;){D=x.lastIndexOf(q,z);if(D<0){break;}C=x.indexOf(m,D);if(D+1>C){break;}p=x.substring(D+1,C);G=p;u=null;B=G.indexOf(r);if(B>-1){u=G.substring(B+1);G=G.substring(0,B);}t=y[G];if(E){t=E(G,t,u);}if(f.isObject(t)){if(f.isArray(t)){t=f.dump(t,parseInt(u,10));}else{u=u||"";n=u.indexOf(A);if(n>-1){u=u.substring(4);}w=t.toString();if(w===i||n>-1){t=f.dump(t,parseInt(u,10));}else{t=w;}}}else{if(!f.isString(t)&&!f.isNumber(t)){t="~-"+F.length+"-~";F[F.length]=p;}}x=x.substring(0,D)+t+x.substring(C+1);if(l===false){z=D-1;}}for(D=F.length-1;D>=0;D=D-1){x=x.replace(new RegExp("~-"+D+"-~"),"{"+F[D]+"}","g");}return x;},trim:function(j){try{return j.replace(/^\s+|\s+$/g,"");}catch(k){return j; +}},merge:function(){var n={},k=arguments,j=k.length,m;for(m=0;m + * YAHOO.env.getVersion for the description of the version data structure. + * @property listener + * @type Function + * @static + * @default undefined + */ + +/** + * Set to true if the library will be dynamically loaded after window.onload. + * Defaults to false + * @property injecting + * @type boolean + * @static + * @default undefined + */ + +/** + * Instructs the yuiloader component to dynamically load yui components and + * their dependencies. See the yuiloader documentation for more information + * about dynamic loading + * @property load + * @static + * @default undefined + * @see yuiloader + */ + +/** + * Forces the use of the supplied locale where applicable in the library + * @property locale + * @type string + * @static + * @default undefined + */ + +if (typeof YAHOO == "undefined" || !YAHOO) { + /** + * The YAHOO global namespace object. If YAHOO is already defined, the + * existing YAHOO object will not be overwritten so that defined + * namespaces are preserved. + * @class YAHOO + * @static + */ + var YAHOO = {}; +} + +/** + * Returns the namespace specified and creates it if it doesn't exist + *
    + * YAHOO.namespace("property.package");
    + * YAHOO.namespace("YAHOO.property.package");
    + * 
    + * Either of the above would create YAHOO.property, then + * YAHOO.property.package + * + * Be careful when naming packages. Reserved words may work in some browsers + * and not others. For instance, the following will fail in Safari: + *
    + * YAHOO.namespace("really.long.nested.namespace");
    + * 
    + * This fails because "long" is a future reserved word in ECMAScript + * + * For implementation code that uses YUI, do not create your components + * in the namespaces defined by YUI ( + * YAHOO.util, + * YAHOO.widget, + * YAHOO.lang, + * YAHOO.tool, + * YAHOO.example, + * YAHOO.env) -- create your own namespace (e.g., 'companyname'). + * + * @method namespace + * @static + * @param {String*} arguments 1-n namespaces to create + * @return {Object} A reference to the last namespace object created + */ +YAHOO.namespace = function() { + var a=arguments, o=null, i, j, d; + for (i=0; i + *
    name:
    The name of the module
    + *
    version:
    The version in use
    + *
    build:
    The build number in use
    + *
    versions:
    All versions that were registered
    + *
    builds:
    All builds that were registered.
    + *
    mainClass:
    An object that was was stamped with the + * current version and build. If + * mainClass.VERSION != version or mainClass.BUILD != build, + * multiple versions of pieces of the library have been + * loaded, potentially causing issues.
    + * + * + * @method getVersion + * @static + * @param {String} name the name of the module (event, slider, etc) + * @return {Object} The version info + */ +YAHOO.env.getVersion = function(name) { + return YAHOO.env.modules[name] || null; +}; + +/** + * Do not fork for a browser if it can be avoided. Use feature detection when + * you can. Use the user agent as a last resort. YAHOO.env.ua stores a version + * number for the browser engine, 0 otherwise. This value may or may not map + * to the version number of the browser using the engine. The value is + * presented as a float so that it can easily be used for boolean evaluation + * as well as for looking for a particular range of versions. Because of this, + * some of the granularity of the version info may be lost (e.g., Gecko 1.8.0.9 + * reports 1.8). + * @class YAHOO.env.ua + * @static + */ + +/** + * parses a user agent string (or looks for one in navigator to parse if + * not supplied). + * @method parseUA + * @since 2.9.0 + * @static + */ +YAHOO.env.parseUA = function(agent) { + + var numberify = function(s) { + var c = 0; + return parseFloat(s.replace(/\./g, function() { + return (c++ == 1) ? '' : '.'; + })); + }, + + nav = navigator, + + o = { + + /** + * Internet Explorer version number or 0. Example: 6 + * @property ie + * @type float + * @static + */ + ie: 0, + + /** + * Opera version number or 0. Example: 9.2 + * @property opera + * @type float + * @static + */ + opera: 0, + + /** + * Gecko engine revision number. Will evaluate to 1 if Gecko + * is detected but the revision could not be found. Other browsers + * will be 0. Example: 1.8 + *
    +         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
    +         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
    +         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
    +         * Firefox 3.0   <-- 1.9
    +         * Firefox 3.5   <-- 1.91
    +         * 
    + * @property gecko + * @type float + * @static + */ + gecko: 0, + + /** + * AppleWebKit version. KHTML browsers that are not WebKit browsers + * will evaluate to 1, other browsers 0. Example: 418.9 + *
    +         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
    +         *                                   latest available for Mac OSX 10.3.
    +         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
    +         * Safari 2.0.4:         418     <-- preventDefault fixed
    +         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
    +         *                                   different versions of webkit
    +         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
    +         *                                   updated, but not updated
    +         *                                   to the latest patch.
    +         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
    +         * SVG and many major issues fixed).
    +         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
    +         * update from 2.x via the 10.4.11 OS patch.
    +         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
    +         *                                   yahoo.com user agent hack removed.
    +         * 
    + * http://en.wikipedia.org/wiki/Safari_version_history + * @property webkit + * @type float + * @static + */ + webkit: 0, + + /** + * Chrome will be detected as webkit, but this property will also + * be populated with the Chrome version number + * @property chrome + * @type float + * @static + */ + chrome: 0, + + /** + * The mobile property will be set to a string containing any relevant + * user agent information when a modern mobile browser is detected. + * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series + * devices with the WebKit-based browser, and Opera Mini. + * @property mobile + * @type string + * @static + */ + mobile: null, + + /** + * Adobe AIR version number or 0. Only populated if webkit is detected. + * Example: 1.0 + * @property air + * @type float + */ + air: 0, + /** + * Detects Apple iPad's OS version + * @property ipad + * @type float + * @static + */ + ipad: 0, + /** + * Detects Apple iPhone's OS version + * @property iphone + * @type float + * @static + */ + iphone: 0, + /** + * Detects Apples iPod's OS version + * @property ipod + * @type float + * @static + */ + ipod: 0, + /** + * General truthy check for iPad, iPhone or iPod + * @property ios + * @type float + * @static + */ + ios: null, + /** + * Detects Googles Android OS version + * @property android + * @type float + * @static + */ + android: 0, + /** + * Detects Palms WebOS version + * @property webos + * @type float + * @static + */ + webos: 0, + + /** + * Google Caja version number or 0. + * @property caja + * @type float + */ + caja: nav && nav.cajaVersion, + + /** + * Set to true if the page appears to be in SSL + * @property secure + * @type boolean + * @static + */ + secure: false, + + /** + * The operating system. Currently only detecting windows or macintosh + * @property os + * @type string + * @static + */ + os: null + + }, + + ua = agent || (navigator && navigator.userAgent), + + loc = window && window.location, + + href = loc && loc.href, + + m; + + o.secure = href && (href.toLowerCase().indexOf("https") === 0); + + if (ua) { + + if ((/windows|win32/i).test(ua)) { + o.os = 'windows'; + } else if ((/macintosh/i).test(ua)) { + o.os = 'macintosh'; + } else if ((/rhino/i).test(ua)) { + o.os = 'rhino'; + } + + // Modern KHTML browsers should qualify as Safari X-Grade + if ((/KHTML/).test(ua)) { + o.webkit = 1; + } + // Modern WebKit browsers are at least X-Grade + m = ua.match(/AppleWebKit\/([^\s]*)/); + if (m && m[1]) { + o.webkit = numberify(m[1]); + + // Mobile browser check + if (/ Mobile\//.test(ua)) { + o.mobile = 'Apple'; // iPhone or iPod Touch + + m = ua.match(/OS ([^\s]*)/); + if (m && m[1]) { + m = numberify(m[1].replace('_', '.')); + } + o.ios = m; + o.ipad = o.ipod = o.iphone = 0; + + m = ua.match(/iPad|iPod|iPhone/); + if (m && m[0]) { + o[m[0].toLowerCase()] = o.ios; + } + } else { + m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/); + if (m) { + // Nokia N-series, Android, webOS, ex: NokiaN95 + o.mobile = m[0]; + } + if (/webOS/.test(ua)) { + o.mobile = 'WebOS'; + m = ua.match(/webOS\/([^\s]*);/); + if (m && m[1]) { + o.webos = numberify(m[1]); + } + } + if (/ Android/.test(ua)) { + o.mobile = 'Android'; + m = ua.match(/Android ([^\s]*);/); + if (m && m[1]) { + o.android = numberify(m[1]); + } + + } + } + + m = ua.match(/Chrome\/([^\s]*)/); + if (m && m[1]) { + o.chrome = numberify(m[1]); // Chrome + } else { + m = ua.match(/AdobeAIR\/([^\s]*)/); + if (m) { + o.air = m[0]; // Adobe AIR 1.0 or better + } + } + } + + if (!o.webkit) { // not webkit +// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) + m = ua.match(/Opera[\s\/]([^\s]*)/); + if (m && m[1]) { + o.opera = numberify(m[1]); + m = ua.match(/Version\/([^\s]*)/); + if (m && m[1]) { + o.opera = numberify(m[1]); // opera 10+ + } + m = ua.match(/Opera Mini[^;]*/); + if (m) { + o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 + } + } else { // not opera or webkit + m = ua.match(/MSIE\s([^;]*)/); + if (m && m[1]) { + o.ie = numberify(m[1]); + } else { // not opera, webkit, or ie + m = ua.match(/Gecko\/([^\s]*)/); + if (m) { + o.gecko = 1; // Gecko detected, look for revision + m = ua.match(/rv:([^\s\)]*)/); + if (m && m[1]) { + o.gecko = numberify(m[1]); + } + } + } + } + } + } + + return o; +}; + +YAHOO.env.ua = YAHOO.env.parseUA(); + +/* + * Initializes the global by creating the default namespaces and applying + * any new configuration information that is detected. This is the setup + * for env. + * @method init + * @static + * @private + */ +(function() { + YAHOO.namespace("util", "widget", "example"); + /*global YAHOO_config*/ + if ("undefined" !== typeof YAHOO_config) { + var l=YAHOO_config.listener, ls=YAHOO.env.listeners,unique=true, i; + if (l) { + // if YAHOO is loaded multiple times we need to check to see if + // this is a new config object. If it is, add the new component + // load listener to the stack + for (i=0; i': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`' + }, + + // ADD = ["toString", "valueOf", "hasOwnProperty"], + ADD = ["toString", "valueOf"], + + OB = { + + /** + * Determines wheather or not the provided object is an array. + * @method isArray + * @param {any} o The object being testing + * @return {boolean} the result + */ + isArray: function(o) { + return OP.toString.apply(o) === ARRAY_TOSTRING; + }, + + /** + * Determines whether or not the provided object is a boolean + * @method isBoolean + * @param {any} o The object being testing + * @return {boolean} the result + */ + isBoolean: function(o) { + return typeof o === 'boolean'; + }, + + /** + * Determines whether or not the provided object is a function. + * Note: Internet Explorer thinks certain functions are objects: + * + * var obj = document.createElement("object"); + * YAHOO.lang.isFunction(obj.getAttribute) // reports false in IE + * + * var input = document.createElement("input"); // append to body + * YAHOO.lang.isFunction(input.focus) // reports false in IE + * + * You will have to implement additional tests if these functions + * matter to you. + * + * @method isFunction + * @param {any} o The object being testing + * @return {boolean} the result + */ + isFunction: function(o) { + return (typeof o === 'function') || OP.toString.apply(o) === FUNCTION_TOSTRING; + }, + + /** + * Determines whether or not the provided object is null + * @method isNull + * @param {any} o The object being testing + * @return {boolean} the result + */ + isNull: function(o) { + return o === null; + }, + + /** + * Determines whether or not the provided object is a legal number + * @method isNumber + * @param {any} o The object being testing + * @return {boolean} the result + */ + isNumber: function(o) { + return typeof o === 'number' && isFinite(o); + }, + + /** + * Determines whether or not the provided object is of type object + * or function + * @method isObject + * @param {any} o The object being testing + * @return {boolean} the result + */ + isObject: function(o) { +return (o && (typeof o === 'object' || L.isFunction(o))) || false; + }, + + /** + * Determines whether or not the provided object is a string + * @method isString + * @param {any} o The object being testing + * @return {boolean} the result + */ + isString: function(o) { + return typeof o === 'string'; + }, + + /** + * Determines whether or not the provided object is undefined + * @method isUndefined + * @param {any} o The object being testing + * @return {boolean} the result + */ + isUndefined: function(o) { + return typeof o === 'undefined'; + }, + + + /** + * IE will not enumerate native functions in a derived object even if the + * function was overridden. This is a workaround for specific functions + * we care about on the Object prototype. + * @property _IEEnumFix + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @static + * @private + */ + _IEEnumFix: (YAHOO.env.ua.ie) ? function(r, s) { + var i, fname, f; + for (i=0;i + * Returns a copy of the specified string with special HTML characters + * escaped. The following characters will be converted to their + * corresponding character entities: + * & < > " ' / ` + *

    + * + *

    + * This implementation is based on the + * OWASP + * HTML escaping recommendations. In addition to the characters + * in the OWASP recommendation, we also escape the ` + * character, since IE interprets it as an attribute delimiter when used in + * innerHTML. + *

    + * + * @method escapeHTML + * @param {String} html String to escape. + * @return {String} Escaped string. + * @static + * @since 2.9.0 + */ + escapeHTML: function (html) { + return html.replace(/[&<>"'\/`]/g, function (match) { + return HTML_CHARS[match]; + }); + }, + + /** + * Utility to set up the prototype, constructor and superclass properties to + * support an inheritance strategy that can chain constructors and methods. + * Static members will not be inherited. + * + * @method extend + * @static + * @param {Function} subc the object to modify + * @param {Function} superc the object to inherit + * @param {Object} overrides additional properties/methods to add to the + * subclass prototype. These will override the + * matching items obtained from the superclass + * if present. + */ + extend: function(subc, superc, overrides) { + if (!superc||!subc) { + throw new Error("extend failed, please check that " + + "all dependencies are included."); + } + var F = function() {}, i; + F.prototype=superc.prototype; + subc.prototype=new F(); + subc.prototype.constructor=subc; + subc.superclass=superc.prototype; + if (superc.prototype.constructor == OP.constructor) { + superc.prototype.constructor=superc; + } + + if (overrides) { + for (i in overrides) { + if (L.hasOwnProperty(overrides, i)) { + subc.prototype[i]=overrides[i]; + } + } + + L._IEEnumFix(subc.prototype, overrides); + } + }, + + /** + * Applies all properties in the supplier to the receiver if the + * receiver does not have these properties yet. Optionally, one or + * more methods/properties can be specified (as additional + * parameters). This option will overwrite the property if receiver + * has it already. If true is passed as the third parameter, all + * properties will be applied and _will_ overwrite properties in + * the receiver. + * + * @method augmentObject + * @static + * @since 2.3.0 + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @param {String*|boolean} arguments zero or more properties methods + * to augment the receiver with. If none specified, everything + * in the supplier will be used unless it would + * overwrite an existing property in the receiver. If true + * is specified as the third parameter, all properties will + * be applied and will overwrite an existing property in + * the receiver + */ + augmentObject: function(r, s) { + if (!s||!r) { + throw new Error("Absorb failed, verify dependencies."); + } + var a=arguments, i, p, overrideList=a[2]; + if (overrideList && overrideList!==true) { // only absorb the specified properties + for (i=2; i 0) ? L.dump(o[i], d-1) : OBJ); + } else { + s.push(o[i]); + } + s.push(COMMA); + } + if (s.length > 1) { + s.pop(); + } + s.push("]"); + // objects {k1 => v1, k2 => v2} + } else { + s.push("{"); + for (i in o) { + if (L.hasOwnProperty(o, i)) { + s.push(i + ARROW); + if (L.isObject(o[i])) { + s.push((d > 0) ? L.dump(o[i], d-1) : OBJ); + } else { + s.push(o[i]); + } + s.push(COMMA); + } + } + if (s.length > 1) { + s.pop(); + } + s.push("}"); + } + + return s.join(""); + }, + + /** + * Does variable substitution on a string. It scans through the string + * looking for expressions enclosed in { } braces. If an expression + * is found, it is used a key on the object. If there is a space in + * the key, the first word is used for the key and the rest is provided + * to an optional function to be used to programatically determine the + * value (the extra information might be used for this decision). If + * the value for the key in the object, or what is returned from the + * function has a string value, number value, or object value, it is + * substituted for the bracket expression and it repeats. If this + * value is an object, it uses the Object's toString() if this has + * been overridden, otherwise it does a shallow dump of the key/value + * pairs. + * + * By specifying the recurse option, the string is rescanned after + * every replacement, allowing for nested template substitutions. + * The side effect of this option is that curly braces in the + * replacement content must be encoded. + * + * @method substitute + * @since 2.3.0 + * @param s {String} The string that will be modified. + * @param o {Object} An object containing the replacement values + * @param f {Function} An optional function that can be used to + * process each match. It receives the key, + * value, and any extra metadata included with + * the key inside of the braces. + * @param recurse {boolean} default true - if not false, the replaced + * string will be rescanned so that nested substitutions are possible. + * @return {String} the substituted string + */ + substitute: function (s, o, f, recurse) { + var i, j, k, key, v, meta, saved=[], token, lidx=s.length, + DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}', + dump, objstr; + + for (;;) { + i = s.lastIndexOf(LBRACE, lidx); + if (i < 0) { + break; + } + j = s.indexOf(RBRACE, i); + if (i + 1 > j) { + break; + } + + //Extract key and meta info + token = s.substring(i + 1, j); + key = token; + meta = null; + k = key.indexOf(SPACE); + if (k > -1) { + meta = key.substring(k + 1); + key = key.substring(0, k); + } + + // lookup the value + v = o[key]; + + // if a substitution function was provided, execute it + if (f) { + v = f(key, v, meta); + } + + if (L.isObject(v)) { + if (L.isArray(v)) { + v = L.dump(v, parseInt(meta, 10)); + } else { + meta = meta || ""; + + // look for the keyword 'dump', if found force obj dump + dump = meta.indexOf(DUMP); + if (dump > -1) { + meta = meta.substring(4); + } + + objstr = v.toString(); + + // use the toString if it is not the Object toString + // and the 'dump' meta info was not found + if (objstr === OBJECT_TOSTRING || dump > -1) { + v = L.dump(v, parseInt(meta, 10)); + } else { + v = objstr; + } + } + } else if (!L.isString(v) && !L.isNumber(v)) { + // This {block} has no replace string. Save it for later. + v = "~-" + saved.length + "-~"; + saved[saved.length] = token; + + // break; + } + + s = s.substring(0, i) + v + s.substring(j + 1); + + if (recurse === false) { + lidx = i-1; + } + + } + + // restore saved {block}s + for (i=saved.length-1; i>=0; i=i-1) { + s = s.replace(new RegExp("~-" + i + "-~"), "{" + saved[i] + "}", "g"); + } + + return s; + }, + + + /** + * Returns a string without any leading or trailing whitespace. If + * the input is not a string, the input will be returned untouched. + * @method trim + * @since 2.3.0 + * @param s {string} the string to trim + * @return {string} the trimmed string + */ + trim: function(s){ + try { + return s.replace(/^\s+|\s+$/g, ""); + } catch(e) { + return s; + } + }, + + /** + * Returns a new object containing all of the properties of + * all the supplied objects. The properties from later objects + * will overwrite those in earlier objects. + * @method merge + * @since 2.3.0 + * @param arguments {Object*} the objects to merge + * @return the new merged object + */ + merge: function() { + var o={}, a=arguments, l=a.length, i; + for (i=0; i + * var A = function() {}; + * A.prototype.foo = 'foo'; + * var a = new A(); + * a.foo = 'foo'; + * alert(a.hasOwnProperty('foo')); // true + * alert(YAHOO.lang.hasOwnProperty(a, 'foo')); // false when using fallback + * + * @method hasOwnProperty + * @param {any} o The object being testing + * @param prop {string} the name of the property to test + * @return {boolean} the result + */ +L.hasOwnProperty = (OP.hasOwnProperty) ? + function(o, prop) { + return o && o.hasOwnProperty && o.hasOwnProperty(prop); + } : function(o, prop) { + return !L.isUndefined(o[prop]) && + o.constructor.prototype[prop] !== o[prop]; + }; + +// new lang wins +OB.augmentObject(L, OB, true); + +/* + * An alias for YAHOO.lang + * @class YAHOO.util.Lang + */ +YAHOO.util.Lang = L; + +/** + * Same as YAHOO.lang.augmentObject, except it only applies prototype + * properties. This is an alias for augmentProto. + * @see YAHOO.lang.augmentObject + * @method augment + * @static + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @param {String*|boolean} arguments zero or more properties methods to + * augment the receiver with. If none specified, everything + * in the supplier will be used unless it would + * overwrite an existing property in the receiver. if true + * is specified as the third parameter, all properties will + * be applied and will overwrite an existing property in + * the receiver + */ +L.augment = L.augmentProto; + +/** + * An alias for YAHOO.lang.augment + * @for YAHOO + * @method augment + * @static + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @param {String*} arguments zero or more properties methods to + * augment the receiver with. If none specified, everything + * in the supplier will be used unless it would + * overwrite an existing property in the receiver + */ +YAHOO.augment = L.augmentProto; + +/** + * An alias for YAHOO.lang.extend + * @method extend + * @static + * @param {Function} subc the object to modify + * @param {Function} superc the object to inherit + * @param {Object} overrides additional properties/methods to add to the + * subclass prototype. These will override the + * matching items obtained from the superclass if present. + */ +YAHOO.extend = L.extend; + +})(); +YAHOO.register("yahoo", YAHOO, {version: "2.9.0", build: "2800"}); diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuiloader-dom-event/yuiloader-dom-event.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuiloader-dom-event/yuiloader-dom-event.js new file mode 100644 index 0000000..a47bc0c --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/yuiloader-dom-event/yuiloader-dom-event.js @@ -0,0 +1,17 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var b=arguments,g=null,e,c,f;for(e=0;e":">",'"':""","'":"'","/":"/","`":"`"},d=["toString","valueOf"],e={isArray:function(j){return a.toString.apply(j)===c;},isBoolean:function(j){return typeof j==="boolean";},isFunction:function(j){return(typeof j==="function")||a.toString.apply(j)===h;},isNull:function(j){return j===null;},isNumber:function(j){return typeof j==="number"&&isFinite(j);},isObject:function(j){return(j&&(typeof j==="object"||f.isFunction(j)))||false;},isString:function(j){return typeof j==="string";},isUndefined:function(j){return typeof j==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(l,k){var j,n,m;for(j=0;j"'\/`]/g,function(k){return g[k];});},extend:function(m,n,l){if(!n||!m){throw new Error("extend failed, please check that "+"all dependencies are included.");}var k=function(){},j;k.prototype=n.prototype;m.prototype=new k();m.prototype.constructor=m;m.superclass=n.prototype;if(n.prototype.constructor==a.constructor){n.prototype.constructor=n;}if(l){for(j in l){if(f.hasOwnProperty(l,j)){m.prototype[j]=l[j];}}f._IEEnumFix(m.prototype,l);}},augmentObject:function(n,m){if(!m||!n){throw new Error("Absorb failed, verify dependencies.");}var j=arguments,l,o,k=j[2];if(k&&k!==true){for(l=2;l0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}if(r.length>1){r.pop();}r.push("]");}else{r.push("{");for(l in j){if(f.hasOwnProperty(j,l)){r.push(l+m);if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}}if(r.length>1){r.pop();}r.push("}");}return r.join("");},substitute:function(x,y,E,l){var D,C,B,G,t,u,F=[],p,z=x.length,A="dump",r=" ",q="{",m="}",n,w;for(;;){D=x.lastIndexOf(q,z);if(D<0){break;}C=x.indexOf(m,D);if(D+1>C){break;}p=x.substring(D+1,C);G=p;u=null;B=G.indexOf(r);if(B>-1){u=G.substring(B+1);G=G.substring(0,B);}t=y[G];if(E){t=E(G,t,u);}if(f.isObject(t)){if(f.isArray(t)){t=f.dump(t,parseInt(u,10));}else{u=u||"";n=u.indexOf(A);if(n>-1){u=u.substring(4);}w=t.toString();if(w===i||n>-1){t=f.dump(t,parseInt(u,10));}else{t=w;}}}else{if(!f.isString(t)&&!f.isNumber(t)){t="~-"+F.length+"-~";F[F.length]=p;}}x=x.substring(0,D)+t+x.substring(C+1);if(l===false){z=D-1;}}for(D=F.length-1;D>=0;D=D-1){x=x.replace(new RegExp("~-"+D+"-~"),"{"+F[D]+"}","g");}return x;},trim:function(j){try{return j.replace(/^\s+|\s+$/g,"");}catch(k){return j; +}},merge:function(){var n={},k=arguments,j=k.length,m;for(m=0;m=420){z.addEventListener("load",function(){YAHOO.log(x+" DOM2 onload "+u,"info","Get");F(x,u);});}else{t=m[x];if(t.varName){v=YAHOO.util.Get.POLL_FREQ;YAHOO.log("Polling for "+t.varName[0]);t.maxattempts=YAHOO.util.Get.TIMEOUT/v;t.attempts=0;t._cache=t.varName[0].split(".");t.timer=s.later(v,t,function(w){I=this._cache;A=I.length;J=this.win;for(C=0;Cthis.maxattempts){y="Over retry limit, giving up";t.timer.cancel();q(x,y);}else{YAHOO.log(I[C]+" failed, retrying");}return;}}YAHOO.log("Safari poll complete");t.timer.cancel();F(x,u);},null,true);}else{s.later(YAHOO.util.Get.POLL_FREQ,null,F,[x,u]);}}}}else{z.onload=function(){YAHOO.log(x+" onload "+u,"info","Get");F(x,u);};}}};q=function(w,v){YAHOO.log("get failure: "+v,"warn","Get");var u=m[w],t;if(u.onFailure){t=u.scope||u.win;u.onFailure.call(t,a(u,v));}};d=function(z){if(m[z]){var t=m[z],u=t.nodes,x=u.length,C=t.win.document,A=C.getElementsByTagName("head")[0],v,y,w,B;if(t.insertBefore){v=b(t.insertBefore,z);if(v){A=v.parentNode;}}for(y=0;y=m.rollup);if(roll){break;}}}}}else{for(j=0;j=m.rollup);if(roll){break;}}}}}if(roll){r[i]=true;rolled=true;this.getRequires(m);}}}if(!rolled){break;}}},_reduce:function(){var i,j,s,m,r=this.required;for(i in r){if(i in this.loaded){delete r[i];}else{var skinDef=this.parseSkin(i);if(skinDef){if(!skinDef.module){var skin_pre=this.SKIN_PREFIX+skinDef.skin;for(j in r){if(lang.hasOwnProperty(r,j)){m=this.moduleInfo[j];var ext=m&&m.ext;if(!ext&&j!==i&&j.indexOf(skin_pre)>-1){delete r[j];}}}}}else{m=this.moduleInfo[i];s=m&&m.supersedes;if(s){for(j=0;j-1){return true;}if(after&&YUI.ArrayUtil.indexOf(after,bb)>-1){return true;}if(checkOptional&&optional&&YUI.ArrayUtil.indexOf(optional,bb)>-1){return true;}var ss=info[bb]&&info[bb].supersedes;if(ss){for(ii=0;iistartLen){YAHOO.util.Get.script(self._filter(js),{data:self._loading,onSuccess:callback,onFailure:self._onFailure,onTimeout:self._onTimeout,insertBefore:self.insertBefore,charset:self.charset,timeout:self.timeout,scope:self});}else{this.loadNext();}};if(css.length>startLen){YAHOO.util.Get.css(this._filter(css),{data:this._loading,onSuccess:loadScript,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,scope:self});}else{loadScript();}return;}else{this.loadNext(this._loading);}},insert:function(o,type){this.calculate(o);this._loading=true;this.loadType=type;if(this.combine){return this._combine();}if(!type){var self=this;this._internalCallback=function(){self._internalCallback=null;self.insert(null,"js");};this.insert(null,"css");return;}this.loadNext();},sandbox:function(o,type){var self=this,success=function(o){var idx=o.argument[0],name=o.argument[2];self._scriptText[idx]=o.responseText;if(self.onProgress){self.onProgress.call(self.scope,{name:name,scriptText:o.responseText,xhrResponse:o,data:self.data});}self._loadCount++;if(self._loadCount>=self._stopCount){var v=self.varName||"YAHOO";var t="(function() {\n";var b="\nreturn "+v+";\n})();";var ref=eval(t+self._scriptText.join("\n")+b);self._pushEvents(ref);if(ref){self.onSuccess.call(self.scope,{reference:ref,data:self.data});}else{self._onFailure.call(self.varName+" reference failure");}}},failure=function(o){self.onFailure.call(self.scope,{msg:"XHR failure",xhrResponse:o,data:self.data});};self._config(o);if(!self.onSuccess){throw new Error("You must supply an onSuccess handler for your sandbox");}self._sandbox=true;if(!type||type!=="js"){self._internalCallback=function(){self._internalCallback=null;self.sandbox(null,"js");};self.insert(null,"css");return;}if(!util.Connect){var ld=new YAHOO.util.YUILoader();ld.insert({base:self.base,filter:self.filter,require:"connection",insertBefore:self.insertBefore,charset:self.charset,onSuccess:function(){self.sandbox(null,"js");},scope:self},"js");return;}self._scriptText=[];self._loadCount=0;self._stopCount=self.sorted.length;self._xhr=[];self.calculate();var s=self.sorted,l=s.length,i,m,url;for(i=0;i-1;}}else{}return G;},addClass:function(W,G){return e.Dom.batch(W,e.Dom._addClass,G);},_addClass:function(X,W){var G=false,Y;if(X&&W){Y=e.Dom._getAttribute(X,f)||i;if(!e.Dom._hasClass(X,W)){e.Dom.setAttribute(X,f,a(Y+b+W));G=true;}}else{}return G;},removeClass:function(W,G){return e.Dom.batch(W,e.Dom._removeClass,G);},_removeClass:function(Y,X){var W=false,aa,Z,G;if(Y&&X){aa=e.Dom._getAttribute(Y,f)||i;e.Dom.setAttribute(Y,f,aa.replace(e.Dom._getClassRegex(X),i));Z=e.Dom._getAttribute(Y,f);if(aa!==Z){e.Dom.setAttribute(Y,f,a(Z));W=true;if(e.Dom._getAttribute(Y,f)===""){G=(Y.hasAttribute&&Y.hasAttribute(E))?E:f;Y.removeAttribute(G);}}}else{}return W;},replaceClass:function(X,W,G){return e.Dom.batch(X,e.Dom._replaceClass,{from:W,to:G});},_replaceClass:function(Y,X){var W,ab,aa,G=false,Z;if(Y&&X){ab=X.from;aa=X.to;if(!aa){G=false;}else{if(!ab){G=e.Dom._addClass(Y,X.to);}else{if(ab!==aa){Z=e.Dom._getAttribute(Y,f)||i;W=(b+Z.replace(e.Dom._getClassRegex(ab),b+aa).replace(/\s+/g,b)).split(e.Dom._getClassRegex(aa));W.splice(1,0,b+aa);e.Dom.setAttribute(Y,f,a(W.join(i)));G=true;}}}}else{}return G;},generateId:function(G,X){X=X||"yui-gen";var W=function(Y){if(Y&&Y.id){return Y.id;}var Z=X+YAHOO.env._id_counter++; +if(Y){if(Y[C]&&Y[C].getElementById(Z)){return e.Dom.generateId(Y,Z+X);}Y.id=Z;}return Z;};return e.Dom.batch(G,W,e.Dom,true)||W.apply(e.Dom,arguments);},isAncestor:function(W,X){W=e.Dom.get(W);X=e.Dom.get(X);var G=false;if((W&&X)&&(W[K]&&X[K])){if(W.contains&&W!==X){G=W.contains(X);}else{if(W.compareDocumentPosition){G=!!(W.compareDocumentPosition(X)&16);}}}else{}return G;},inDocument:function(G,W){return e.Dom._inDoc(e.Dom.get(G),W);},_inDoc:function(W,X){var G=false;if(W&&W[c]){X=X||W[C];G=e.Dom.isAncestor(X[U],W);}else{}return G;},getElementsBy:function(W,af,ab,ad,X,ac,ae){af=af||"*";ab=(ab)?e.Dom.get(ab):null||j;var aa=(ae)?null:[],G;if(ab){G=ab.getElementsByTagName(af);for(var Y=0,Z=G.length;Y=8){e.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(d,e,a,c){this.top=d;this.y=d;this[1]=d;this.right=e;this.bottom=a;this.left=c;this.x=c;this[0]=c;this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(a){return(a.left>=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(f){var d=Math.max(this.top,f.top),e=Math.min(this.right,f.right),a=Math.min(this.bottom,f.bottom),c=Math.max(this.left,f.left); +if(a>=d&&e>=c){return new YAHOO.util.Region(d,e,a,c);}else{return null;}};YAHOO.util.Region.prototype.union=function(f){var d=Math.min(this.top,f.top),e=Math.max(this.right,f.right),a=Math.max(this.bottom,f.bottom),c=Math.min(this.left,f.left);return new YAHOO.util.Region(d,e,a,c);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(e){var g=YAHOO.util.Dom.getXY(e),d=g[1],f=g[0]+e.offsetWidth,a=g[1]+e.offsetHeight,c=g[0];return new YAHOO.util.Region(d,f,a,c);};YAHOO.util.Point=function(a,b){if(YAHOO.lang.isArray(a)){b=a[1];a=a[0];}YAHOO.util.Point.superclass.constructor.call(this,b,a,b,a);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var b=YAHOO.util,a="clientTop",f="clientLeft",j="parentNode",k="right",w="hasLayout",i="px",u="opacity",l="auto",d="borderLeftWidth",g="borderTopWidth",p="borderRightWidth",v="borderBottomWidth",s="visible",q="transparent",n="height",e="width",h="style",t="currentStyle",r=/^width|height$/,o=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,m={get:function(x,z){var y="",A=x[t][z];if(z===u){y=b.Dom.getStyle(x,u);}else{if(!A||(A.indexOf&&A.indexOf(i)>-1)){y=A;}else{if(b.Dom.IE_COMPUTED[z]){y=b.Dom.IE_COMPUTED[z](x,z);}else{if(o.test(A)){y=b.Dom.IE.ComputedStyle.getPixel(x,z);}else{y=A;}}}}return y;},getOffset:function(z,E){var B=z[t][E],x=E.charAt(0).toUpperCase()+E.substr(1),C="offset"+x,y="pixel"+x,A="",D;if(B==l){D=z[C];if(D===undefined){A=0;}A=D;if(r.test(E)){z[h][E]=D;if(z[C]>D){A=D-(z[C]-D);}z[h][E]=l;}}else{if(!z[h][y]&&!z[h][E]){z[h][E]=B;}A=z[h][y];}return A+i;},getBorderWidth:function(x,z){var y=null;if(!x[t][w]){x[h].zoom=1;}switch(z){case g:y=x[a];break;case v:y=x.offsetHeight-x.clientHeight-x[a];break;case d:y=x[f];break;case p:y=x.offsetWidth-x.clientWidth-x[f];break;}return y+i;},getPixel:function(y,x){var A=null,B=y[t][k],z=y[t][x];y[h][k]=z;A=y[h].pixelRight;y[h][k]=B;return A+i;},getMargin:function(y,x){var z;if(y[t][x]==l){z=0+i;}else{z=b.Dom.IE.ComputedStyle.getPixel(y,x);}return z;},getVisibility:function(y,x){var z;while((z=y[t])&&z[x]=="inherit"){y=y[j];}return(z)?z[x]:s;},getColor:function(y,x){return b.Dom.Color.toRGB(y[t][x])||q;},getBorderColor:function(y,x){var z=y[t],A=z[x]||z.color;return b.Dom.Color.toRGB(b.Dom.Color.toHex(A));}},c={};c.top=c.right=c.bottom=c.left=c[e]=c[n]=m.getOffset;c.color=m.getColor;c[g]=c[p]=c[v]=c[d]=m.getBorderWidth;c.marginTop=c.marginRight=c.marginBottom=c.marginLeft=m.getMargin;c.visibility=m.getVisibility;c.borderColor=c.borderTopColor=c.borderRightColor=c.borderBottomColor=c.borderLeftColor=m.getBorderColor;b.Dom.IE_COMPUTED=c;b.Dom.IE_ComputedStyle=m;})();(function(){var c="toString",a=parseInt,b=RegExp,d=YAHOO.util;d.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(e){if(!d.Dom.Color.re_RGB.test(e)){e=d.Dom.Color.toHex(e);}if(d.Dom.Color.re_hex.exec(e)){e="rgb("+[a(b.$1,16),a(b.$2,16),a(b.$3,16)].join(", ")+")";}return e;},toHex:function(f){f=d.Dom.Color.KEYWORDS[f]||f;if(d.Dom.Color.re_RGB.exec(f)){f=[Number(b.$1).toString(16),Number(b.$2).toString(16),Number(b.$3).toString(16)];for(var e=0;e0){i=c[0];}try{b=g.fn.call(f,i,g.obj);}catch(h){this.lastError=h;if(a){throw h;}}}else{try{b=g.fn.call(f,this.type,c,g.obj);}catch(d){this.lastError=d;if(a){throw d;}}}return b;},unsubscribeAll:function(){var a=this.subscribers.length,b;for(b=a-1;b>-1;b--){this._delete(b);}this.subscribers=[];return a;},_delete:function(a){var b=this.subscribers[a];if(b){delete b.fn;delete b.obj;}this.subscribers.splice(a,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(a,b,c){this.fn=a;this.obj=YAHOO.lang.isUndefined(b)?null:b;this.overrideContext=c;};YAHOO.util.Subscriber.prototype.getScope=function(a){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return a;};YAHOO.util.Subscriber.prototype.contains=function(a,b){if(b){return(this.fn==a&&this.obj==b);}else{return(this.fn==a);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var g=false,h=[],j=[],a=0,e=[],b=0,c={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},d=YAHOO.env.ua.ie,f="focusin",i="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:d,_interval:null,_dri:null,_specialTypes:{focusin:(d?"focusin":"focus"),focusout:(d?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(q,m,o,p,n){var k=(YAHOO.lang.isString(q))?[q]:q;for(var l=0;l-1;m--){s=(this.removeListener(l[m],k,r)&&s);}return s;}}if(!r||!r.call){return this.purgeElement(l,false,k);}if("unload"==k){for(m=j.length-1;m>-1;m--){u=j[m];if(u&&u[0]==l&&u[1]==k&&u[2]==r){j.splice(m,1);return true;}}return false;}var n=null;var o=arguments[3];if("undefined"===typeof o){o=this._getCacheIndex(h,l,k,r);}if(o>=0){n=h[o];}if(!l||!n){return false;}var t=n[this.CAPTURE]===true?true:false;try{this._simpleRemove(l,k,n[this.WFN],t);}catch(q){this.lastError=q;return false;}delete h[o][this.WFN];delete h[o][this.FN];h.splice(o,1);return true;},getTarget:function(m,l){var k=m.target||m.srcElement;return this.resolveTextNode(k);},resolveTextNode:function(l){try{if(l&&3==l.nodeType){return l.parentNode;}}catch(k){return null;}return l;},getPageX:function(l){var k=l.pageX;if(!k&&0!==k){k=l.clientX||0;if(this.isIE){k+=this._getScrollLeft();}}return k;},getPageY:function(k){var l=k.pageY;if(!l&&0!==l){l=k.clientY||0;if(this.isIE){l+=this._getScrollTop();}}return l;},getXY:function(k){return[this.getPageX(k),this.getPageY(k)];},getRelatedTarget:function(l){var k=l.relatedTarget; +if(!k){if(l.type=="mouseout"){k=l.toElement;}else{if(l.type=="mouseover"){k=l.fromElement;}}}return this.resolveTextNode(k);},getTime:function(m){if(!m.time){var l=new Date().getTime();try{m.time=l;}catch(k){this.lastError=k;return l;}}return m.time;},stopEvent:function(k){this.stopPropagation(k);this.preventDefault(k);},stopPropagation:function(k){if(k.stopPropagation){k.stopPropagation();}else{k.cancelBubble=true;}},preventDefault:function(k){if(k.preventDefault){k.preventDefault();}else{k.returnValue=false;}},getEvent:function(m,k){var l=m||window.event;if(!l){var n=this.getEvent.caller;while(n){l=n.arguments[0];if(l&&Event==l.constructor){break;}n=n.caller;}}return l;},getCharCode:function(l){var k=l.keyCode||l.charCode||0;if(YAHOO.env.ua.webkit&&(k in c)){k=c[k];}return k;},_getCacheIndex:function(n,q,r,p){for(var o=0,m=n.length;o0&&e.length>0);}var p=[];var r=function(t,u){var s=t;if(u.overrideContext){if(u.overrideContext===true){s=u.obj;}else{s=u.overrideContext;}}u.fn.call(s,u.obj);};var l,k,o,n,m=[];for(l=0,k=e.length;l-1;l--){o=e[l];if(!o||!o.id){e.splice(l,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(p,q,s){var n=(YAHOO.lang.isString(p))?this.getEl(p):p;var r=this.getListeners(n,s),o,k;if(r){for(o=r.length-1;o>-1;o--){var m=r[o];this.removeListener(n,m.type,m.fn);}}if(q&&n&&n.childNodes){for(o=0,k=n.childNodes.length;o-1;o--){n=h[o];if(n){try{m.removeListener(n[m.EL],n[m.TYPE],n[m.FN],o);}catch(v){}}}n=null;}try{m._simpleRemove(window,"unload",m._unload);m._simpleRemove(window,"load",m._load);}catch(u){}},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var k=document.documentElement,l=document.body;if(k&&(k.scrollTop||k.scrollLeft)){return[k.scrollTop,k.scrollLeft];}else{if(l){return[l.scrollTop,l.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(m,n,l,k){m.addEventListener(n,l,(k));};}else{if(window.attachEvent){return function(m,n,l,k){m.attachEvent("on"+n,l);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(m,n,l,k){m.removeEventListener(n,l,(k));};}else{if(window.detachEvent){return function(l,m,k){l.detachEvent("on"+m,k);};}else{return function(){};}}}()};}();(function(){var a=YAHOO.util.Event;a.on=a.addListener;a.onFocus=a.addFocusListener;a.onBlur=a.addBlurListener; +/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ +if(a.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;a._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var b=document.createElement("p");a._dri=setInterval(function(){try{b.doScroll("left");clearInterval(a._dri);a._dri=null;a._ready();b=null;}catch(c){}},a.POLL_INTERVAL);}}else{if(a.webkit&&a.webkit<525){a._dri=setInterval(function(){var c=document.readyState;if("loaded"==c||"complete"==c){clearInterval(a._dri);a._dri=null;a._ready();}},a.POLL_INTERVAL);}else{a._simpleAdd(document,"DOMContentLoaded",a._ready);}}a._simpleAdd(window,"load",a._load);a._simpleAdd(window,"unload",a._unload);a._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(a,c,f,e){this.__yui_events=this.__yui_events||{};var d=this.__yui_events[a];if(d){d.subscribe(c,f,e);}else{this.__yui_subscribers=this.__yui_subscribers||{};var b=this.__yui_subscribers;if(!b[a]){b[a]=[];}b[a].push({fn:c,obj:f,overrideContext:e});}},unsubscribe:function(c,e,g){this.__yui_events=this.__yui_events||{};var a=this.__yui_events;if(c){var f=a[c];if(f){return f.unsubscribe(e,g);}}else{var b=true;for(var d in a){if(YAHOO.lang.hasOwnProperty(a,d)){b=b&&a[d].unsubscribe(e,g); +}}return b;}return false;},unsubscribeAll:function(a){return this.unsubscribe(a);},createEvent:function(b,g){this.__yui_events=this.__yui_events||{};var e=g||{},d=this.__yui_events,f;if(d[b]){}else{f=new YAHOO.util.CustomEvent(b,e.scope||this,e.silent,YAHOO.util.CustomEvent.FLAT,e.fireOnce);d[b]=f;if(e.onSubscribeCallback){f.subscribeEvent.subscribe(e.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var a=this.__yui_subscribers[b];if(a){for(var c=0;c 0){ + return YAHOO.lang.substitute(customMessage, { message: defaultMessage }); + } else { + return defaultMessage; + } + }, + + //------------------------------------------------------------------------- + // Generic Assertion Methods + //------------------------------------------------------------------------- + + /** + * Forces an assertion error to occur. + * @param {String} message (Optional) The message to display with the failure. + * @method fail + * @static + */ + fail : function (message /*:String*/) /*:Void*/ { + throw new YAHOO.util.AssertionError(this._formatMessage(message, "Test force-failed.")); + }, + + //------------------------------------------------------------------------- + // Equality Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is equal to another. This uses the double equals sign + * so type coercion may occur. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areEqual + * @static + */ + areEqual : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (expected != actual) { + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be equal."), expected, actual); + } + }, + + /** + * Asserts that a value is not equal to another. This uses the double equals sign + * so type coercion may occur. + * @param {Object} unexpected The unexpected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areNotEqual + * @static + */ + areNotEqual : function (unexpected /*:Object*/, actual /*:Object*/, + message /*:String*/) /*:Void*/ { + if (unexpected == actual) { + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be equal."), unexpected); + } + }, + + /** + * Asserts that a value is not the same as another. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} unexpected The unexpected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areNotSame + * @static + */ + areNotSame : function (unexpected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (unexpected === actual) { + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be the same."), unexpected); + } + }, + + /** + * Asserts that a value is the same as another. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areSame + * @static + */ + areSame : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (expected !== actual) { + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be the same."), expected, actual); + } + }, + + //------------------------------------------------------------------------- + // Boolean Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is false. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isFalse + * @static + */ + isFalse : function (actual /*:Boolean*/, message /*:String*/) { + if (false !== actual) { + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be false."), false, actual); + } + }, + + /** + * Asserts that a value is true. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isTrue + * @static + */ + isTrue : function (actual /*:Boolean*/, message /*:String*/) /*:Void*/ { + if (true !== actual) { + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be true."), true, actual); + } + + }, + + //------------------------------------------------------------------------- + // Special Value Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is not a number. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNaN + * @static + */ + isNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{ + if (!isNaN(actual)){ + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be NaN."), NaN, actual); + } + }, + + /** + * Asserts that a value is not the special NaN value. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotNaN + * @static + */ + isNotNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{ + if (isNaN(actual)){ + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be NaN."), NaN); + } + }, + + /** + * Asserts that a value is not null. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotNull + * @static + */ + isNotNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (YAHOO.lang.isNull(actual)) { + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be null."), null); + } + }, + + /** + * Asserts that a value is not undefined. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotUndefined + * @static + */ + isNotUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (YAHOO.lang.isUndefined(actual)) { + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should not be undefined."), undefined); + } + }, + + /** + * Asserts that a value is null. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNull + * @static + */ + isNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isNull(actual)) { + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be null."), null, actual); + } + }, + + /** + * Asserts that a value is undefined. This uses the triple equals sign + * so no type coercion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isUndefined + * @static + */ + isUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isUndefined(actual)) { + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be undefined."), undefined, actual); + } + }, + + //-------------------------------------------------------------------------- + // Instance Assertion Methods + //-------------------------------------------------------------------------- + + /** + * Asserts that a value is an array. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isArray + * @static + */ + isArray : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isArray(actual)){ + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an array."), actual); + } + }, + + /** + * Asserts that a value is a Boolean. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isBoolean + * @static + */ + isBoolean : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isBoolean(actual)){ + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a Boolean."), actual); + } + }, + + /** + * Asserts that a value is a function. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isFunction + * @static + */ + isFunction : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isFunction(actual)){ + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a function."), actual); + } + }, + + /** + * Asserts that a value is an instance of a particular object. This may return + * incorrect results when comparing objects from one frame to constructors in + * another frame. For best results, don't use in a cross-frame manner. + * @param {Function} expected The function that the object should be an instance of. + * @param {Object} actual The object to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isInstanceOf + * @static + */ + isInstanceOf : function (expected /*:Function*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!(actual instanceof expected)){ + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value isn't an instance of expected type."), expected, actual); + } + }, + + /** + * Asserts that a value is a number. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNumber + * @static + */ + isNumber : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isNumber(actual)){ + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a number."), actual); + } + }, + + /** + * Asserts that a value is an object. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isObject + * @static + */ + isObject : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isObject(actual)){ + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an object."), actual); + } + }, + + /** + * Asserts that a value is a string. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isString + * @static + */ + isString : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.isString(actual)){ + throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a string."), actual); + } + }, + + /** + * Asserts that a value is of a particular type. + * @param {String} expectedType The expected type of the variable. + * @param {Object} actualValue The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isTypeOf + * @static + */ + isTypeOf : function (expected /*:String*/, actual /*:Object*/, message /*:String*/) /*:Void*/{ + if (typeof actual != expected){ + throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be of type " + expected + "."), expected, typeof actual); + } + } +}; + +//----------------------------------------------------------------------------- +// Assertion errors +//----------------------------------------------------------------------------- + +/** + * AssertionError is thrown whenever an assertion fails. It provides methods + * to more easily get at error information and also provides a base class + * from which more specific assertion errors can be derived. + * + * @param {String} message The message to display when the error occurs. + * @namespace YAHOO.util + * @class AssertionError + * @extends Error + * @constructor + */ +YAHOO.util.AssertionError = function (message /*:String*/){ + + //call superclass + //arguments.callee.superclass.constructor.call(this, message); + + /* + * Error message. Must be duplicated to ensure browser receives it. + * @type String + * @property message + */ + this.message /*:String*/ = message; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name /*:String*/ = "AssertionError"; +}; + +//inherit methods +YAHOO.lang.extend(YAHOO.util.AssertionError, Object, { + + /** + * Returns a fully formatted error for an assertion failure. This should + * be overridden by all subclasses to provide specific information. + * @method getMessage + * @return {String} A string describing the error. + */ + getMessage : function () /*:String*/ { + return this.message; + }, + + /** + * Returns a string representation of the error. + * @method toString + * @return {String} A string representation of the error. + */ + toString : function () /*:String*/ { + return this.name + ": " + this.getMessage(); + } + +}); + +/** + * ComparisonFailure is subclass of AssertionError that is thrown whenever + * a comparison between two values fails. It provides mechanisms to retrieve + * both the expected and actual value. + * + * @param {String} message The message to display when the error occurs. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value that caused the assertion to fail. + * @namespace YAHOO.util + * @extends YAHOO.util.AssertionError + * @class ComparisonFailure + * @constructor + */ +YAHOO.util.ComparisonFailure = function (message /*:String*/, expected /*:Object*/, actual /*:Object*/){ + + //call superclass + YAHOO.util.AssertionError.call(this, message); + + /** + * The expected value. + * @type Object + * @property expected + */ + this.expected /*:Object*/ = expected; + + /** + * The actual value. + * @type Object + * @property actual + */ + this.actual /*:Object*/ = actual; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name /*:String*/ = "ComparisonFailure"; + +}; + +//inherit methods +YAHOO.lang.extend(YAHOO.util.ComparisonFailure, YAHOO.util.AssertionError, { + + /** + * Returns a fully formatted error for an assertion failure. This message + * provides information about the expected and actual values. + * @method toString + * @return {String} A string describing the error. + */ + getMessage : function () /*:String*/ { + return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")" + + "\nActual:" + this.actual + " (" + (typeof this.actual) + ")"; + } + +}); + +/** + * UnexpectedValue is subclass of AssertionError that is thrown whenever + * a value was unexpected in its scope. This typically means that a test + * was performed to determine that a value was *not* equal to a certain + * value. + * + * @param {String} message The message to display when the error occurs. + * @param {Object} unexpected The unexpected value. + * @namespace YAHOO.util + * @extends YAHOO.util.AssertionError + * @class UnexpectedValue + * @constructor + */ +YAHOO.util.UnexpectedValue = function (message /*:String*/, unexpected /*:Object*/){ + + //call superclass + YAHOO.util.AssertionError.call(this, message); + + /** + * The unexpected value. + * @type Object + * @property unexpected + */ + this.unexpected /*:Object*/ = unexpected; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name /*:String*/ = "UnexpectedValue"; + +}; + +//inherit methods +YAHOO.lang.extend(YAHOO.util.UnexpectedValue, YAHOO.util.AssertionError, { + + /** + * Returns a fully formatted error for an assertion failure. The message + * contains information about the unexpected value that was encountered. + * @method getMessage + * @return {String} A string describing the error. + */ + getMessage : function () /*:String*/ { + return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") "; + } + +}); + +/** + * ShouldFail is subclass of AssertionError that is thrown whenever + * a test was expected to fail but did not. + * + * @param {String} message The message to display when the error occurs. + * @namespace YAHOO.util + * @extends YAHOO.util.AssertionError + * @class ShouldFail + * @constructor + */ +YAHOO.util.ShouldFail = function (message /*:String*/){ + + //call superclass + YAHOO.util.AssertionError.call(this, message || "This test should fail but didn't."); + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name /*:String*/ = "ShouldFail"; + +}; + +//inherit methods +YAHOO.lang.extend(YAHOO.util.ShouldFail, YAHOO.util.AssertionError); + +/** + * ShouldError is subclass of AssertionError that is thrown whenever + * a test is expected to throw an error but doesn't. + * + * @param {String} message The message to display when the error occurs. + * @namespace YAHOO.util + * @extends YAHOO.util.AssertionError + * @class ShouldError + * @constructor + */ +YAHOO.util.ShouldError = function (message /*:String*/){ + + //call superclass + YAHOO.util.AssertionError.call(this, message || "This test should have thrown an error but didn't."); + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name /*:String*/ = "ShouldError"; + +}; + +//inherit methods +YAHOO.lang.extend(YAHOO.util.ShouldError, YAHOO.util.AssertionError); + +/** + * UnexpectedError is subclass of AssertionError that is thrown whenever + * an error occurs within the course of a test and the test was not expected + * to throw an error. + * + * @param {Error} cause The unexpected error that caused this error to be + * thrown. + * @namespace YAHOO.util + * @extends YAHOO.util.AssertionError + * @class UnexpectedError + * @constructor + */ +YAHOO.util.UnexpectedError = function (cause /*:Object*/){ + + //call superclass + YAHOO.util.AssertionError.call(this, "Unexpected error: " + cause.message); + + /** + * The unexpected error that occurred. + * @type Error + * @property cause + */ + this.cause /*:Error*/ = cause; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name /*:String*/ = "UnexpectedError"; + + /** + * Stack information for the error (if provided). + * @type String + * @property stack + */ + this.stack /*:String*/ = cause.stack; + +}; + +//inherit methods +YAHOO.lang.extend(YAHOO.util.UnexpectedError, YAHOO.util.AssertionError); +//----------------------------------------------------------------------------- +// ArrayAssert object +//----------------------------------------------------------------------------- + +/** + * The ArrayAssert object provides functions to test JavaScript array objects + * for a variety of cases. + * + * @namespace YAHOO.util + * @class ArrayAssert + * @static + */ + +YAHOO.util.ArrayAssert = { + + /** + * Asserts that a value is present in an array. This uses the triple equals + * sign so no type coercion may occur. + * @param {Object} needle The value that is expected in the array. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method contains + * @static + */ + contains : function (needle /*:Object*/, haystack /*:Array*/, + message /*:String*/) /*:Void*/ { + + var found /*:Boolean*/ = false; + var Assert = YAHOO.util.Assert; + + //begin checking values + for (var i=0; i < haystack.length && !found; i++){ + if (haystack[i] === needle) { + found = true; + } + } + + if (!found){ + Assert.fail(Assert._formatMessage(message, "Value " + needle + " (" + (typeof needle) + ") not found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a set of values are present in an array. This uses the triple equals + * sign so no type coercion may occur. For this assertion to pass, all values must + * be found. + * @param {Object[]} needles An array of values that are expected in the array. + * @param {Array} haystack An array of values to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method containsItems + * @static + */ + containsItems : function (needles /*:Object[]*/, haystack /*:Array*/, + message /*:String*/) /*:Void*/ { + + //begin checking values + for (var i=0; i < needles.length; i++){ + this.contains(needles[i], haystack, message); + } + }, + + /** + * Asserts that a value matching some condition is present in an array. This uses + * a function to determine a match. + * @param {Function} matcher A function that returns true if the items matches or false if not. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method containsMatch + * @static + */ + containsMatch : function (matcher /*:Function*/, haystack /*:Array*/, + message /*:String*/) /*:Void*/ { + + //check for valid matcher + if (typeof matcher != "function"){ + throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function."); + } + + var found /*:Boolean*/ = false; + var Assert = YAHOO.util.Assert; + + //begin checking values + for (var i=0; i < haystack.length && !found; i++){ + if (matcher(haystack[i])) { + found = true; + } + } + + if (!found){ + Assert.fail(Assert._formatMessage(message, "No match found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a value is not present in an array. This uses the triple equals + * sign so no type coercion may occur. + * @param {Object} needle The value that is expected in the array. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContain + * @static + */ + doesNotContain : function (needle /*:Object*/, haystack /*:Array*/, + message /*:String*/) /*:Void*/ { + + var found /*:Boolean*/ = false; + var Assert = YAHOO.util.Assert; + + //begin checking values + for (var i=0; i < haystack.length && !found; i++){ + if (haystack[i] === needle) { + found = true; + } + } + + if (found){ + Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a set of values are not present in an array. This uses the triple equals + * sign so no type coercion may occur. For this assertion to pass, all values must + * not be found. + * @param {Object[]} needles An array of values that are not expected in the array. + * @param {Array} haystack An array of values to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContainItems + * @static + */ + doesNotContainItems : function (needles /*:Object[]*/, haystack /*:Array*/, + message /*:String*/) /*:Void*/ { + + for (var i=0; i < needles.length; i++){ + this.doesNotContain(needles[i], haystack, message); + } + + }, + + /** + * Asserts that no values matching a condition are present in an array. This uses + * a function to determine a match. + * @param {Function} matcher A function that returns true if the items matches or false if not. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContainMatch + * @static + */ + doesNotContainMatch : function (matcher /*:Function*/, haystack /*:Array*/, + message /*:String*/) /*:Void*/ { + + //check for valid matcher + if (typeof matcher != "function"){ + throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function."); + } + + var found /*:Boolean*/ = false; + var Assert = YAHOO.util.Assert; + + //begin checking values + for (var i=0; i < haystack.length && !found; i++){ + if (matcher(haystack[i])) { + found = true; + } + } + + if (found){ + Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that the given value is contained in an array at the specified index. + * This uses the triple equals sign so no type coercion will occur. + * @param {Object} needle The value to look for. + * @param {Array} haystack The array to search in. + * @param {int} index The index at which the value should exist. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method indexOf + * @static + */ + indexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ { + + //try to find the value in the array + for (var i=0; i < haystack.length; i++){ + if (haystack[i] === needle){ + YAHOO.util.Assert.areEqual(index, i, message || "Value exists at index " + i + " but should be at index " + index + "."); + return; + } + } + + var Assert = YAHOO.util.Assert; + + //if it makes it here, it wasn't found at all + Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array [" + haystack + "].")); + }, + + /** + * Asserts that the values in an array are equal, and in the same position, + * as values in another array. This uses the double equals sign + * so type coercion may occur. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method itemsAreEqual + * @static + */ + itemsAreEqual : function (expected /*:Array*/, actual /*:Array*/, + message /*:String*/) /*:Void*/ { + + //one may be longer than the other, so get the maximum length + var len /*:int*/ = Math.max(expected.length, actual.length || 0); + var Assert = YAHOO.util.Assert; + + //begin checking values + for (var i=0; i < len; i++){ + Assert.areEqual(expected[i], actual[i], + Assert._formatMessage(message, "Values in position " + i + " are not equal.")); + } + }, + + /** + * Asserts that the values in an array are equivalent, and in the same position, + * as values in another array. This uses a function to determine if the values + * are equivalent. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {Function} comparator A function that returns true if the values are equivalent + * or false if not. + * @param {String} message (Optional) The message to display if the assertion fails. + * @return {Void} + * @method itemsAreEquivalent + * @static + */ + itemsAreEquivalent : function (expected /*:Array*/, actual /*:Array*/, + comparator /*:Function*/, message /*:String*/) /*:Void*/ { + + //make sure the comparator is valid + if (typeof comparator != "function"){ + throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function."); + } + + //one may be longer than the other, so get the maximum length + var len /*:int*/ = Math.max(expected.length, actual.length || 0); + + //begin checking values + for (var i=0; i < len; i++){ + if (!comparator(expected[i], actual[i])){ + throw new YAHOO.util.ComparisonFailure(YAHOO.util.Assert._formatMessage(message, "Values in position " + i + " are not equivalent."), expected[i], actual[i]); + } + } + }, + + /** + * Asserts that an array is empty. + * @param {Array} actual The array to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isEmpty + * @static + */ + isEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ { + if (actual.length > 0){ + var Assert = YAHOO.util.Assert; + Assert.fail(Assert._formatMessage(message, "Array should be empty.")); + } + }, + + /** + * Asserts that an array is not empty. + * @param {Array} actual The array to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotEmpty + * @static + */ + isNotEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ { + if (actual.length === 0){ + var Assert = YAHOO.util.Assert; + Assert.fail(Assert._formatMessage(message, "Array should not be empty.")); + } + }, + + /** + * Asserts that the values in an array are the same, and in the same position, + * as values in another array. This uses the triple equals sign + * so no type coercion will occur. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method itemsAreSame + * @static + */ + itemsAreSame : function (expected /*:Array*/, actual /*:Array*/, + message /*:String*/) /*:Void*/ { + + //one may be longer than the other, so get the maximum length + var len /*:int*/ = Math.max(expected.length, actual.length || 0); + var Assert = YAHOO.util.Assert; + + //begin checking values + for (var i=0; i < len; i++){ + Assert.areSame(expected[i], actual[i], + Assert._formatMessage(message, "Values in position " + i + " are not the same.")); + } + }, + + /** + * Asserts that the given value is contained in an array at the specified index, + * starting from the back of the array. + * This uses the triple equals sign so no type coercion will occur. + * @param {Object} needle The value to look for. + * @param {Array} haystack The array to search in. + * @param {int} index The index at which the value should exist. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method lastIndexOf + * @static + */ + lastIndexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ { + + var Assert = YAHOO.util.Assert; + + //try to find the value in the array + for (var i=haystack.length; i >= 0; i--){ + if (haystack[i] === needle){ + Assert.areEqual(index, i, Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + ".")); + return; + } + } + + //if it makes it here, it wasn't found at all + Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array.")); + } + +}; +YAHOO.namespace("util"); + + +//----------------------------------------------------------------------------- +// ObjectAssert object +//----------------------------------------------------------------------------- + +/** + * The ObjectAssert object provides functions to test JavaScript objects + * for a variety of cases. + * + * @namespace YAHOO.util + * @class ObjectAssert + * @static + */ +YAHOO.util.ObjectAssert = { + + /** + * Asserts that all properties in the object exist in another object. + * @param {Object} expected An object with the expected properties. + * @param {Object} actual An object with the actual properties. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method propertiesAreEqual + * @static + */ + propertiesAreEqual : function (expected /*:Object*/, actual /*:Object*/, + message /*:String*/) /*:Void*/ { + + var Assert = YAHOO.util.Assert; + + //get all properties in the object + var properties /*:Array*/ = []; + for (var property in expected){ + properties.push(property); + } + + //see if the properties are in the expected object + for (var i=0; i < properties.length; i++){ + Assert.isNotUndefined(actual[properties[i]], + Assert._formatMessage(message, "Property '" + properties[i] + "' expected.")); + } + + }, + + /** + * Asserts that an object has a property with the given name. + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method hasProperty + * @static + */ + hasProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ { + if (!(propertyName in object)){ + var Assert = YAHOO.util.Assert; + Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object.")); + } + }, + + /** + * Asserts that a property with the given name exists on an object instance (not on its prototype). + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method hasProperty + * @static + */ + hasOwnProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ { + if (!YAHOO.lang.hasOwnProperty(object, propertyName)){ + var Assert = YAHOO.util.Assert; + Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance.")); + } + } +}; +//----------------------------------------------------------------------------- +// DateAssert object +//----------------------------------------------------------------------------- + +/** + * The DateAssert object provides functions to test JavaScript Date objects + * for a variety of cases. + * + * @namespace YAHOO.util + * @class DateAssert + * @static + */ + +YAHOO.util.DateAssert = { + + /** + * Asserts that a date's month, day, and year are equal to another date's. + * @param {Date} expected The expected date. + * @param {Date} actual The actual date to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method datesAreEqual + * @static + */ + datesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){ + if (expected instanceof Date && actual instanceof Date){ + var Assert = YAHOO.util.Assert; + Assert.areEqual(expected.getFullYear(), actual.getFullYear(), Assert._formatMessage(message, "Years should be equal.")); + Assert.areEqual(expected.getMonth(), actual.getMonth(), Assert._formatMessage(message, "Months should be equal.")); + Assert.areEqual(expected.getDate(), actual.getDate(), Assert._formatMessage(message, "Day of month should be equal.")); + } else { + throw new TypeError("DateAssert.datesAreEqual(): Expected and actual values must be Date objects."); + } + }, + + /** + * Asserts that a date's hour, minutes, and seconds are equal to another date's. + * @param {Date} expected The expected date. + * @param {Date} actual The actual date to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method timesAreEqual + * @static + */ + timesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){ + if (expected instanceof Date && actual instanceof Date){ + var Assert = YAHOO.util.Assert; + Assert.areEqual(expected.getHours(), actual.getHours(), Assert._formatMessage(message, "Hours should be equal.")); + Assert.areEqual(expected.getMinutes(), actual.getMinutes(), Assert._formatMessage(message, "Minutes should be equal.")); + Assert.areEqual(expected.getSeconds(), actual.getSeconds(), Assert._formatMessage(message, "Seconds should be equal.")); + } else { + throw new TypeError("DateAssert.timesAreEqual(): Expected and actual values must be Date objects."); + } + } + +}; +YAHOO.namespace("tool"); + +//----------------------------------------------------------------------------- +// TestManager object +//----------------------------------------------------------------------------- + +/** + * Runs pages containing test suite definitions. + * @namespace YAHOO.tool + * @class TestManager + * @static + */ +YAHOO.tool.TestManager = { + + /** + * Constant for the testpagebegin custom event + * @property TEST_PAGE_BEGIN_EVENT + * @static + * @type string + * @final + */ + TEST_PAGE_BEGIN_EVENT /*:String*/ : "testpagebegin", + + /** + * Constant for the testpagecomplete custom event + * @property TEST_PAGE_COMPLETE_EVENT + * @static + * @type string + * @final + */ + TEST_PAGE_COMPLETE_EVENT /*:String*/ : "testpagecomplete", + + /** + * Constant for the testmanagerbegin custom event + * @property TEST_MANAGER_BEGIN_EVENT + * @static + * @type string + * @final + */ + TEST_MANAGER_BEGIN_EVENT /*:String*/ : "testmanagerbegin", + + /** + * Constant for the testmanagercomplete custom event + * @property TEST_MANAGER_COMPLETE_EVENT + * @static + * @type string + * @final + */ + TEST_MANAGER_COMPLETE_EVENT /*:String*/ : "testmanagercomplete", + + //------------------------------------------------------------------------- + // Private Properties + //------------------------------------------------------------------------- + + + /** + * The URL of the page currently being executed. + * @type String + * @private + * @property _curPage + * @static + */ + _curPage /*:String*/ : null, + + /** + * The frame used to load and run tests. + * @type Window + * @private + * @property _frame + * @static + */ + _frame /*:Window*/ : null, + + /** + * The logger used to output results from the various tests. + * @type YAHOO.tool.TestLogger + * @private + * @property _logger + * @static + */ + _logger : null, + + /** + * The timeout ID for the next iteration through the tests. + * @type int + * @private + * @property _timeoutId + * @static + */ + _timeoutId /*:int*/ : 0, + + /** + * Array of pages to load. + * @type String[] + * @private + * @property _pages + * @static + */ + _pages /*:String[]*/ : [], + + /** + * Aggregated results + * @type Object + * @private + * @property _results + * @static + */ + _results: null, + + //------------------------------------------------------------------------- + // Private Methods + //------------------------------------------------------------------------- + + /** + * Handles TestRunner.COMPLETE_EVENT, storing the results and beginning + * the loop again. + * @param {Object} data Data about the event. + * @return {Void} + * @private + * @static + */ + _handleTestRunnerComplete : function (data /*:Object*/) /*:Void*/ { + + this.fireEvent(this.TEST_PAGE_COMPLETE_EVENT, { + page: this._curPage, + results: data.results + }); + + //save results + //this._results[this.curPage] = data.results; + + //process 'em + this._processResults(this._curPage, data.results); + + this._logger.clearTestRunner(); + + //if there's more to do, set a timeout to begin again + if (this._pages.length){ + this._timeoutId = setTimeout(function(){ + YAHOO.tool.TestManager._run(); + }, 1000); + } else { + this.fireEvent(this.TEST_MANAGER_COMPLETE_EVENT, this._results); + } + }, + + /** + * Processes the results of a test page run, outputting log messages + * for failed tests. + * @return {Void} + * @private + * @static + */ + _processResults : function (page /*:String*/, results /*:Object*/) /*:Void*/ { + + var r = this._results; + + r.passed += results.passed; + r.failed += results.failed; + r.ignored += results.ignored; + r.total += results.total; + r.duration += results.duration; + + if (results.failed){ + r.failedPages.push(page); + } else { + r.passedPages.push(page); + } + + results.name = page; + results.type = "page"; + + r[page] = results; + }, + + /** + * Loads the next test page into the iframe. + * @return {Void} + * @static + * @private + */ + _run : function () /*:Void*/ { + + //set the current page + this._curPage = this._pages.shift(); + + this.fireEvent(this.TEST_PAGE_BEGIN_EVENT, this._curPage); + + //load the frame - destroy history in case there are other iframes that + //need testing + this._frame.location.replace(this._curPage); + + }, + + //------------------------------------------------------------------------- + // Public Methods + //------------------------------------------------------------------------- + + /** + * Signals that a test page has been loaded. This should be called from + * within the test page itself to notify the TestManager that it is ready. + * @return {Void} + * @static + */ + load : function () /*:Void*/ { + if (parent.YAHOO.tool.TestManager !== this){ + parent.YAHOO.tool.TestManager.load(); + } else { + + if (this._frame) { + //assign event handling + var TestRunner = this._frame.YAHOO.tool.TestRunner; + + this._logger.setTestRunner(TestRunner); + TestRunner.subscribe(TestRunner.COMPLETE_EVENT, this._handleTestRunnerComplete, this, true); + + //run it + TestRunner.run(); + } + } + }, + + /** + * Sets the pages to be loaded. + * @param {String[]} pages An array of URLs to load. + * @return {Void} + * @static + */ + setPages : function (pages /*:String[]*/) /*:Void*/ { + this._pages = pages; + }, + + /** + * Begins the process of running the tests. + * @return {Void} + * @static + */ + start : function () /*:Void*/ { + + if (!this._initialized) { + + /** + * Fires when loading a test page + * @event testpagebegin + * @param curPage {string} the page being loaded + * @static + */ + this.createEvent(this.TEST_PAGE_BEGIN_EVENT); + + /** + * Fires when a test page is complete + * @event testpagecomplete + * @param obj {page: string, results: object} the name of the + * page that was loaded, and the test suite results + * @static + */ + this.createEvent(this.TEST_PAGE_COMPLETE_EVENT); + + /** + * Fires when the test manager starts running all test pages + * @event testmanagerbegin + * @static + */ + this.createEvent(this.TEST_MANAGER_BEGIN_EVENT); + + /** + * Fires when the test manager finishes running all test pages. External + * test runners should subscribe to this event in order to get the + * aggregated test results. + * @event testmanagercomplete + * @param obj { pages_passed: int, pages_failed: int, tests_passed: int + * tests_failed: int, passed: string[], failed: string[], + * page_results: {} } + * @static + */ + this.createEvent(this.TEST_MANAGER_COMPLETE_EVENT); + + //create iframe if not already available + if (!this._frame){ + var frame /*:HTMLElement*/ = document.createElement("iframe"); + frame.style.visibility = "hidden"; + frame.style.position = "absolute"; + document.body.appendChild(frame); + this._frame = frame.contentWindow || frame.contentDocument.parentWindow; + } + + //create test logger if not already available + if (!this._logger){ + this._logger = new YAHOO.tool.TestLogger(); + } + + this._initialized = true; + } + + + // reset the results cache + this._results = { + + passed: 0, + failed: 0, + ignored: 0, + total: 0, + type: "report", + name: "YUI Test Results", + duration: 0, + failedPages:[], + passedPages:[] + /* + // number of pages that pass + pages_passed: 0, + // number of pages that fail + pages_failed: 0, + // total number of tests passed + tests_passed: 0, + // total number of tests failed + tests_failed: 0, + // array of pages that passed + passed: [], + // array of pages that failed + failed: [], + // map of full results for each page + page_results: {}*/ + }; + + this.fireEvent(this.TEST_MANAGER_BEGIN_EVENT, null); + this._run(); + + }, + + /** + * Stops the execution of tests. + * @return {Void} + * @static + */ + stop : function () /*:Void*/ { + clearTimeout(this._timeoutId); + } + +}; + +YAHOO.lang.augmentObject(YAHOO.tool.TestManager, YAHOO.util.EventProvider.prototype); + +YAHOO.namespace("tool"); + +//----------------------------------------------------------------------------- +// TestLogger object +//----------------------------------------------------------------------------- + +/** + * Displays test execution progress and results, providing filters based on + * different key events. + * @namespace YAHOO.tool + * @class TestLogger + * @constructor + * @param {HTMLElement} element (Optional) The element to create the logger in. + * @param {Object} config (Optional) Configuration options for the logger. + */ +YAHOO.tool.TestLogger = function (element, config) { + YAHOO.tool.TestLogger.superclass.constructor.call(this, element, config); + this.init(); +}; + +YAHOO.lang.extend(YAHOO.tool.TestLogger, YAHOO.widget.LogReader, { + + footerEnabled : true, + newestOnTop : false, + + /** + * Formats message string to HTML for output to console. + * @private + * @method formatMsg + * @param oLogMsg {Object} Log message object. + * @return {String} HTML-formatted message for output to console. + */ + formatMsg : function(message /*:Object*/) { + + var category /*:String*/ = message.category; + var text /*:String*/ = this.html2Text(message.msg); + + return "

    " + category.toUpperCase() + " " + text + "

    "; + + }, + + //------------------------------------------------------------------------- + // Private Methods + //------------------------------------------------------------------------- + + /* + * Initializes the logger. + * @private + */ + init : function () { + + //attach to any available TestRunner + if (YAHOO.tool.TestRunner){ + this.setTestRunner(YAHOO.tool.TestRunner); + } + + //hide useless sources + this.hideSource("global"); + this.hideSource("LogReader"); + + //hide useless message categories + this.hideCategory("warn"); + this.hideCategory("window"); + this.hideCategory("time"); + + //reset the logger + this.clearConsole(); + }, + + /** + * Clears the reference to the TestRunner from previous operations. This + * unsubscribes all events and removes the object reference. + * @return {Void} + * @static + */ + clearTestRunner : function () /*:Void*/ { + if (this._runner){ + this._runner.unsubscribeAll(); + this._runner = null; + } + }, + + /** + * Sets the source test runner that the logger should monitor. + * @param {YAHOO.tool.TestRunner} testRunner The TestRunner to observe. + * @return {Void} + * @static + */ + setTestRunner : function (testRunner /*:YAHOO.tool.TestRunner*/) /*:Void*/ { + + if (this._runner){ + this.clearTestRunner(); + } + + this._runner = testRunner; + + //setup event _handlers + testRunner.subscribe(testRunner.TEST_PASS_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.TEST_FAIL_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.TEST_IGNORE_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.BEGIN_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.COMPLETE_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.TEST_SUITE_BEGIN_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.TEST_SUITE_COMPLETE_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.TEST_CASE_BEGIN_EVENT, this._handleTestRunnerEvent, this, true); + testRunner.subscribe(testRunner.TEST_CASE_COMPLETE_EVENT, this._handleTestRunnerEvent, this, true); + }, + + //------------------------------------------------------------------------- + // Event Handlers + //------------------------------------------------------------------------- + + /** + * Handles all TestRunner events, outputting appropriate data into the console. + * @param {Object} data The event data object. + * @return {Void} + * @private + */ + _handleTestRunnerEvent : function (data /*:Object*/) /*:Void*/ { + + //shortcut variables + var TestRunner /*:Object*/ = YAHOO.tool.TestRunner; + + //data variables + var message /*:String*/ = ""; + var messageType /*:String*/ = ""; + + switch(data.type){ + case TestRunner.BEGIN_EVENT: + message = "Testing began at " + (new Date()).toString() + "."; + messageType = "info"; + break; + + case TestRunner.COMPLETE_EVENT: + message = "Testing completed at " + (new Date()).toString() + ".\nPassed:" + + data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total; + messageType = "info"; + break; + + case TestRunner.TEST_FAIL_EVENT: + message = data.testName + ": " + data.error.getMessage(); + messageType = "fail"; + break; + + case TestRunner.TEST_IGNORE_EVENT: + message = data.testName + ": ignored."; + messageType = "ignore"; + break; + + case TestRunner.TEST_PASS_EVENT: + message = data.testName + ": passed."; + messageType = "pass"; + break; + + case TestRunner.TEST_SUITE_BEGIN_EVENT: + message = "Test suite \"" + data.testSuite.name + "\" started."; + messageType = "info"; + break; + + case TestRunner.TEST_SUITE_COMPLETE_EVENT: + message = "Test suite \"" + data.testSuite.name + "\" completed.\nPassed:" + + data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total; + messageType = "info"; + break; + + case TestRunner.TEST_CASE_BEGIN_EVENT: + message = "Test case \"" + data.testCase.name + "\" started."; + messageType = "info"; + break; + + case TestRunner.TEST_CASE_COMPLETE_EVENT: + message = "Test case \"" + data.testCase.name + "\" completed.\nPassed:" + + data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total; + messageType = "info"; + break; + default: + message = "Unexpected event " + data.type; + message = "info"; + } + + YAHOO.log(message, messageType, "TestRunner"); + } + +}); +YAHOO.namespace("tool.TestFormat"); + +(function(){ + + /** + * Returns test results formatted as a JSON string. Requires JSON utility. + * @param {Object} result The results object created by TestRunner. + * @return {String} An XML-formatted string of results. + * @namespace YAHOO.tool.TestFormat + * @method JSON + * @static + */ + YAHOO.tool.TestFormat.JSON = function(results) { + return YAHOO.lang.JSON.stringify(results); + }; + + /* (intentionally not documented) + * Simple escape function for XML attribute values. + * @param {String} text The text to escape. + * @return {String} The escaped text. + */ + function xmlEscape(text){ + return text.replace(/["'<>&]/g, function(c){ + switch(c){ + case "<": return "<"; + case ">": return ">"; + case "\"": return """; + case "'": return "'"; + case "&": return "&"; + } + }); + } + + /** + * Returns test results formatted as an XML string. + * @param {Object} result The results object created by TestRunner. + * @return {String} An XML-formatted string of results. + * @namespace YAHOO.tool.TestFormat + * @method XML + * @static + */ + YAHOO.tool.TestFormat.XML = function(results) { + + function serializeToXML(results){ + var l = YAHOO.lang, + xml = "<" + results.type + " name=\"" + xmlEscape(results.name) + "\""; + + if (l.isNumber(results.duration)){ + xml += " duration=\"" + results.duration + "\""; + } + + if (results.type == "test"){ + xml += " result=\"" + results.result + "\" message=\"" + xmlEscape(results.message) + "\">"; + } else { + xml += " passed=\"" + results.passed + "\" failed=\"" + results.failed + "\" ignored=\"" + results.ignored + "\" total=\"" + results.total + "\">"; + for (var prop in results) { + if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ + xml += serializeToXML(results[prop]); + } + } + } + + xml += ""; + + return xml; + } + + return "" + serializeToXML(results); + + }; + + + /** + * Returns test results formatted in JUnit XML format. + * @param {Object} result The results object created by TestRunner. + * @return {String} An XML-formatted string of results. + * @namespace YAHOO.tool.TestFormat + * @method JUnitXML + * @static + */ + YAHOO.tool.TestFormat.JUnitXML = function(results) { + + + function serializeToJUnitXML(results){ + var l = YAHOO.lang, + xml = "", + prop; + + switch (results.type){ + //equivalent to testcase in JUnit + case "test": + if (results.result != "ignore"){ + xml = ""; + if (results.result == "fail"){ + xml += ""; + } + xml+= ""; + } + break; + + //equivalent to testsuite in JUnit + case "testcase": + + xml = ""; + + for (prop in results) { + if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ + xml += serializeToJUnitXML(results[prop]); + } + } + + xml += ""; + break; + + case "testsuite": + for (prop in results) { + if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ + xml += serializeToJUnitXML(results[prop]); + } + } + + //skip output - no JUnit equivalent + break; + + case "report": + + xml = ""; + + for (prop in results) { + if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ + xml += serializeToJUnitXML(results[prop]); + } + } + + xml += ""; + + //no default + } + + return xml; + + } + + return "" + serializeToJUnitXML(results); + }; + + /** + * Returns test results formatted in TAP format. + * For more information, see Test Anything Protocol. + * @param {Object} result The results object created by TestRunner. + * @return {String} A TAP-formatted string of results. + * @namespace YAHOO.tool.TestFormat + * @method TAP + * @static + */ + YAHOO.tool.TestFormat.TAP = function(results) { + + var currentTestNum = 1; + + function serializeToTAP(results){ + var l = YAHOO.lang, + text = ""; + + switch (results.type){ + + case "test": + if (results.result != "ignore"){ + + text = "ok " + (currentTestNum++) + " - " + results.name; + + if (results.result == "fail"){ + text = "not " + text + " - " + results.message; + } + + text += "\n"; + } else { + text = "#Ignored test " + results.name + "\n"; + } + break; + + case "testcase": + + text = "#Begin testcase " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; + + + for (prop in results) { + if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ + text += serializeToTAP(results[prop]); + } + } + + text += "#End testcase " + results.name + "\n"; + + + break; + + case "testsuite": + + text = "#Begin testsuite " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; + + for (prop in results) { + if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ + text += serializeToTAP(results[prop]); + } + } + + text += "#End testsuite " + results.name + "\n"; + break; + + case "report": + + for (prop in results) { + if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ + text += serializeToTAP(results[prop]); + } + } + + //no default + } + + return text; + + } + + return "1.." + results.total + "\n" + serializeToTAP(results); + }; + +})(); +YAHOO.namespace("tool.CoverageFormat"); + +/** + * Returns the coverage report in JSON format. This is the straight + * JSON representation of the native coverage report. + * @param {Object} coverage The coverage report object. + * @return {String} A JSON-formatted string of coverage data. + * @method JSON + * @namespace YAHOO.tool.CoverageFormat + */ +YAHOO.tool.CoverageFormat.JSON = function(coverage){ + return YAHOO.lang.JSON.stringify(coverage); +}; + +/** + * Returns the coverage report in a JSON format compatible with + * Xdebug. See Xdebug Documentation + * for more information. Note: function coverage is not available + * in this format. + * @param {Object} coverage The coverage report object. + * @return {String} A JSON-formatted string of coverage data. + * @method XdebugJSON + * @namespace YAHOO.tool.CoverageFormat + */ +YAHOO.tool.CoverageFormat.XdebugJSON = function(coverage){ + var report = {}, + prop; + for (prop in coverage){ + if (coverage.hasOwnProperty(prop)){ + report[prop] = coverage[prop].lines; + } + } + + return YAHOO.lang.JSON.stringify(report); +}; + +YAHOO.namespace("tool"); + +/** + * An object capable of sending test results to a server. + * @param {String} url The URL to submit the results to. + * @param {Function} format (Optiona) A function that outputs the results in a specific format. + * Default is YAHOO.tool.TestFormat.XML. + * @constructor + * @namespace YAHOO.tool + * @class TestReporter + */ +YAHOO.tool.TestReporter = function(url /*:String*/, format /*:Function*/) { + + /** + * The URL to submit the data to. + * @type String + * @property url + */ + this.url /*:String*/ = url; + + /** + * The formatting function to call when submitting the data. + * @type Function + * @property format + */ + this.format /*:Function*/ = format || YAHOO.tool.TestFormat.XML; + + /** + * Extra fields to submit with the request. + * @type Object + * @property _fields + * @private + */ + this._fields /*:Object*/ = new Object(); + + /** + * The form element used to submit the results. + * @type HTMLFormElement + * @property _form + * @private + */ + this._form /*:HTMLElement*/ = null; + + /** + * Iframe used as a target for form submission. + * @type HTMLIFrameElement + * @property _iframe + * @private + */ + this._iframe /*:HTMLElement*/ = null; +}; + +YAHOO.tool.TestReporter.prototype = { + + //restore missing constructor + constructor: YAHOO.tool.TestReporter, + + /** + * Convert a date into ISO format. + * From Douglas Crockford's json2.js + * @param {Date} date The date to convert. + * @return {String} An ISO-formatted date string + * @method _convertToISOString + * @private + */ + _convertToISOString: function(date){ + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return date.getUTCFullYear() + '-' + + f(date.getUTCMonth() + 1) + '-' + + f(date.getUTCDate()) + 'T' + + f(date.getUTCHours()) + ':' + + f(date.getUTCMinutes()) + ':' + + f(date.getUTCSeconds()) + 'Z'; + + }, + + /** + * Adds a field to the form that submits the results. + * @param {String} name The name of the field. + * @param {Variant} value The value of the field. + * @return {Void} + * @method addField + */ + addField : function (name /*:String*/, value /*:Variant*/) /*:Void*/{ + this._fields[name] = value; + }, + + /** + * Removes all previous defined fields. + * @return {Void} + * @method addField + */ + clearFields : function() /*:Void*/{ + this._fields = new Object(); + }, + + /** + * Cleans up the memory associated with the TestReporter, removing DOM elements + * that were created. + * @return {Void} + * @method destroy + */ + destroy : function() /*:Void*/ { + if (this._form){ + this._form.parentNode.removeChild(this._form); + this._form = null; + } + if (this._iframe){ + this._iframe.parentNode.removeChild(this._iframe); + this._iframe = null; + } + this._fields = null; + }, + + /** + * Sends the report to the server. + * @param {Object} results The results object created by TestRunner. + * @return {Void} + * @method report + */ + report : function(results /*:Object*/) /*:Void*/{ + + //if the form hasn't been created yet, create it + if (!this._form){ + this._form = document.createElement("form"); + this._form.method = "post"; + this._form.style.visibility = "hidden"; + this._form.style.position = "absolute"; + this._form.style.top = 0; + document.body.appendChild(this._form); + + //IE won't let you assign a name using the DOM, must do it the hacky way + if (YAHOO.env.ua.ie){ + this._iframe = document.createElement("