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/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/api/bbm/lib/net_rim_bb_qm_platform.jar b/api/bbm/lib/net_rim_bb_qm_platform.jar index 1a173ba..34543e7 100644 Binary files a/api/bbm/lib/net_rim_bb_qm_platform.jar and b/api/bbm/lib/net_rim_bb_qm_platform.jar differ diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformContextListenerImpl.java b/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformContextListenerImpl.java index 3e2f3bd..5949ed2 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformContextListenerImpl.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformContextListenerImpl.java @@ -17,9 +17,15 @@ import net.rim.blackberry.api.bbm.platform.BBMPlatformContext; import net.rim.blackberry.api.bbm.platform.BBMPlatformContextListener; +import net.rim.blackberry.api.bbm.platform.profile.BBMPlatformContact; +import net.rim.blackberry.api.bbm.platform.profile.Presence; +import net.rim.blackberry.api.bbm.platform.profile.UserProfile; import net.rim.blackberry.api.bbm.platform.profile.UserProfileBoxItem; +import net.rim.device.api.script.Scriptable; import net.rim.device.api.script.ScriptableFunction; +import blackberry.bbm.platform.self.SelfNamespace; import blackberry.bbm.platform.self.profilebox.ScriptableProfileBoxItem; +import blackberry.bbm.platform.users.BBMPlatformUser; import blackberry.bbm.platform.util.ConstantsUtil; import blackberry.bbm.platform.util.Util; @@ -60,7 +66,7 @@ public void accessChanged(boolean isAccessAllowed, int code) { Util.dispatchCallback(callback, args); } - public void appInvoked(int reason, Object param) { + public void appInvoked(int reason, Object param, Presence user) { final ScriptableFunction callback; try { callback = (ScriptableFunction) _platform.getField(BBMPlatformNamespace.EVENT_ON_APP_INVOKED); @@ -68,15 +74,47 @@ public void appInvoked(int reason, Object param) { return; } - final Object[] args; - if(reason == BBMPlatformContext.INVOKE_PROFILE_BOX_ITEM) { - final ScriptableProfileBoxItem scriptItem = - new ScriptableProfileBoxItem(_platform.getProfileBox(), (UserProfileBoxItem) param); - args = new Object[] { "profilebox", scriptItem }; + // Get reason string and scriptable param + final String reasonStr; + final Object scriptableParam; + switch(reason) { + case BBMPlatformContext.INVOKE_PROFILE_BOX_ITEM: + reasonStr = "profilebox"; + scriptableParam = new ScriptableProfileBoxItem(_platform.getProfileBox(), (UserProfileBoxItem) param); + break; + case BBMPlatformContext.INVOKE_PROFILE_BOX: + reasonStr = "profileboxtitle"; + scriptableParam = Scriptable.UNDEFINED; + break; + case BBMPlatformContext.INVOKE_PERSONAL_MESSAGE: + reasonStr = "personalmessage"; + scriptableParam = (String) param; + break; + case BBMPlatformContext.INVOKE_CHAT_MESSAGE: + reasonStr = "chatmessage"; + scriptableParam = Scriptable.UNDEFINED; + break; + default: + // Don't invoke if we don't know what to do with the reason + return; + } + + // Get scriptable user: either self namespace of BBMPlatformUser instance + final Object scriptableUser; + if(user instanceof UserProfile) { + scriptableUser = SelfNamespace.getInstance(); + } else if(user instanceof BBMPlatformContact) { + scriptableUser = new BBMPlatformUser(user); } else { - return; + scriptableUser = Scriptable.UNDEFINED; } + final Object[] args = { + reasonStr, + scriptableParam, + scriptableUser, + }; Util.dispatchCallback(callback, args); } + } diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformNamespace.java b/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformNamespace.java index 2e07e7a..1b60388 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformNamespace.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformNamespace.java @@ -27,6 +27,7 @@ import blackberry.bbm.platform.io.IONamespace; import blackberry.bbm.platform.io.MessagingServiceListenerImpl; import blackberry.bbm.platform.self.SelfNamespace; +import blackberry.bbm.platform.settings.SettingsNamespace; import blackberry.bbm.platform.ui.UINamespace; import blackberry.bbm.platform.users.UsersNamespace; import blackberry.bbm.platform.util.ConstantsUtil; @@ -43,6 +44,7 @@ public final class BBMPlatformNamespace extends Scriptable { public static final String FUNC_REGISTER = "register"; public static final String FUNC_REQUEST_USER_PERMISSION = "requestUserPermission"; + public static final String FUNC_SHOW_OPTIONS = "showBBMAppOptions"; public static final String FIELD_ENVIRONMENT = "environment"; public static final String EVENT_ON_APP_INVOKED = "onappinvoked"; public static final String EVENT_ON_ACCESS_CHANGED = "onaccesschanged"; @@ -99,6 +101,8 @@ public Object getField(String name) throws Exception { return new RegisterFunction(); } else if(name.equals(BBMPlatformNamespace.FUNC_REQUEST_USER_PERMISSION)) { return new RequestUserPermissionFunction(); + } else if(name.equals(BBMPlatformNamespace.FUNC_SHOW_OPTIONS)) { + return new ShowOptionsFunction(); } else if(name.equals(SelfNamespace.NAME)) { return SelfNamespace.getInstance(); } else if(name.equals(UsersNamespace.NAME)) { @@ -107,6 +111,8 @@ public Object getField(String name) throws Exception { return IONamespace.getInstance(); } else if(name.equals(UINamespace.NAME)) { return UINamespace.getInstance(); + } else if(name.equals(SettingsNamespace.NAME)) { + return SettingsNamespace.getInstance(); } else if(_wFields.hasField(name)){ return _wFields.getField(name); } else if(name.equals(FIELD_ENVIRONMENT)) { @@ -126,22 +132,42 @@ private Object getEnvironment() { } catch(ControlledAccessException e) { return UNDEFINED; } - } private class RegisterFunction extends ScriptableFunctionBase { - public static final String OPTIONS_FIELD_UUID = "uuid"; + public static final String OPTIONS_FIELD_UUID = "uuid"; + public static final String OPTIONS_FIELD_SHARECONTENTSPLAT = "shareContentSplat"; protected Object execute(Object thiz, Object[] args) throws Exception { final Object onAccessChanged = BBMPlatformNamespace.this.getField(EVENT_ON_ACCESS_CHANGED); if(onAccessChanged.equals(UNDEFINED)) { - throw new IllegalStateException("blackberry.bbm.platform.onAccessChanged == undefined"); + throw new IllegalStateException("blackberry.bbm.platform.onaccesschanged == undefined"); } final Scriptable options = (Scriptable) args[0]; final String uuid = (String) options.getField(OPTIONS_FIELD_UUID); - final BBMPlatformApplication bbmApp = new BBMPlatformApplication(uuid); + + // Get optional shareContentSplat property + final Object shareContentSplatObj = options.getField(OPTIONS_FIELD_SHARECONTENTSPLAT); + boolean shareContentSplat; + try { + shareContentSplat = ((Boolean) shareContentSplatObj).booleanValue(); + } catch(Exception e) { + shareContentSplat = false; + } + final boolean finalShareContentSplat = shareContentSplat; + + final BBMPlatformApplication bbmApp = new BBMPlatformApplication(uuid) { + public int getDefaultSettings() { + if(finalShareContentSplat) { + return super.getDefaultSettings() | BBMPlatformContext.SETTING_SHARECONTENT_SPLAT; + } else { + return super.getDefaultSettings(); + } + + } + }; Dispatcher.getInstance().dispatch(new DispatchableEvent(null) { protected void dispatch() { @@ -196,4 +222,33 @@ protected FunctionSignature[] getFunctionSignatures() { }; } } // RequestUserPermissionFunction + + private class ShowOptionsFunction extends ScriptableFunctionBase { + + protected Object execute(Object thiz, Object[] args) throws Exception { + + final ScriptableFunction onComplete = (ScriptableFunction) args[0]; + + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + _bbmpContext.requestAppSettings(); + Util.dispatchCallback(onComplete, null); + } + }); + } + }); + + return UNDEFINED; + } + + protected FunctionSignature[] getFunctionSignatures() { + FunctionSignature sig1 = new FunctionSignature(1); + sig1.addParam(ScriptableFunction.class, true); + return new FunctionSignature[] { + sig1 + }; + } + } // ShowOptionsFunction } diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/io/MessagingServiceListenerImpl.java b/api/bbm/src/main/java/blackberry/bbm/platform/io/MessagingServiceListenerImpl.java index 8608959..fdfb426 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/io/MessagingServiceListenerImpl.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/io/MessagingServiceListenerImpl.java @@ -15,6 +15,7 @@ */ package blackberry.bbm.platform.io; +import java.util.Date; import java.util.Hashtable; import net.rim.blackberry.api.bbm.platform.io.BBMPlatformChannel; @@ -28,6 +29,7 @@ import net.rim.blackberry.api.bbm.platform.service.MessagingServiceListener; import net.rim.device.api.script.ScriptableFunction; import blackberry.bbm.platform.users.BBMPlatformUser; +import blackberry.bbm.platform.users.UsersNamespace; import blackberry.bbm.platform.util.ConstantsUtil; import blackberry.bbm.platform.util.Util; import blackberry.core.threading.DispatchableEvent; @@ -230,4 +232,21 @@ public void onMessagesExpired(BBMPlatformContact contact, BBMPlatformData[] data }; Util.dispatchCallback(callback, args); } + + public void onShareContentReceived(BBMPlatformContact contact, String description, BBMPlatformData content, long timestamp) { + final ScriptableFunction callback; + try { + callback = (ScriptableFunction) UsersNamespace.getInstance().getField(UsersNamespace.EVENT_ON_SHARE_CONTENT); + } catch(Exception e) { + return; + } + final Object[] args = { + new BBMPlatformUser(contact), + content.getDataAsString(), + description, + new Date(timestamp), + }; + Util.dispatchCallback(callback, args); + } + } diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/self/SelfNamespace.java b/api/bbm/src/main/java/blackberry/bbm/platform/self/SelfNamespace.java index 0f30a9f..bb0c7ca 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/self/SelfNamespace.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/self/SelfNamespace.java @@ -107,7 +107,7 @@ protected void dispatch() { protected FunctionSignature[] getFunctionSignatures() { FunctionSignature sig1 = new FunctionSignature(2); - sig1.addParam(String.class, true); + sig1.addNullableParam(String.class, true); sig1.addParam(ScriptableFunction.class, true); return new FunctionSignature[] { diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/self/profilebox/ProfileBoxNamespace.java b/api/bbm/src/main/java/blackberry/bbm/platform/self/profilebox/ProfileBoxNamespace.java index 9e61eec..0e85801 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/self/profilebox/ProfileBoxNamespace.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/self/profilebox/ProfileBoxNamespace.java @@ -15,6 +15,8 @@ */ package blackberry.bbm.platform.self.profilebox; +import java.nio.ByteBuffer; + import net.rim.blackberry.api.bbm.platform.profile.UserProfile; import net.rim.blackberry.api.bbm.platform.profile.UserProfileBox; import net.rim.blackberry.api.bbm.platform.profile.UserProfileBoxAccessException; @@ -117,8 +119,9 @@ protected Object execute(Object thiz, Object[] args) throws Exception { if(iconURI.equals(UNDEFINED)) { iconID = -1; } else { - final Bitmap icon = Util.requestBitmap((String) iconURI); - iconID = Math.abs(icon.hashCode()); // icon ID is hash code of bitmap + final byte[] iconBytes = Util.requestBitmapBytes((String) iconURI); + final Bitmap icon = Bitmap.createBitmapFromBytes(iconBytes, 0, iconBytes.length, 1); + iconID = Math.abs(ByteBuffer.wrap(iconBytes).hashCode()); // icon ID is hash code of bitmap if(! _profileBox.isIconRegistered(iconID)) { _profileBox.registerIcon(iconID, PNGEncodedImage.encode(icon)); } diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/settings/SettingsNamespace.java b/api/bbm/src/main/java/blackberry/bbm/platform/settings/SettingsNamespace.java new file mode 100644 index 0000000..7dd8032 --- /dev/null +++ b/api/bbm/src/main/java/blackberry/bbm/platform/settings/SettingsNamespace.java @@ -0,0 +1,39 @@ +package blackberry.bbm.platform.settings; + +import blackberry.bbm.platform.BBMPlatformNamespace; +import net.rim.blackberry.api.bbm.platform.SettingsManager; +import net.rim.device.api.script.Scriptable; + +public class SettingsNamespace extends Scriptable { + + public static final String NAME = "settings"; + + private static final String FIELD_PROFILE_BOX = "profileboxEnabled"; + private static final String FIELD_PUBLIC_CONNS = "alwaysAllowPublicConns"; + + private static SettingsNamespace _instance; + + private final SettingsManager _settings; + + public SettingsNamespace(SettingsManager settings) { + _settings = settings; + } + + public static SettingsNamespace getInstance() { + if(_instance == null) { + final SettingsManager settings = BBMPlatformNamespace.getInstance().getContext().getSettingsManager(); + _instance = new SettingsNamespace(settings); + } + return _instance; + } + + public Object getField(String name) throws Exception { + if(name.equals(FIELD_PROFILE_BOX)) { + return new Boolean(_settings.getSetting(SettingsManager.SETTING_PROFILE_BOX) == SettingsManager.VALUE_ENABLED); + } else if(name.equals(FIELD_PUBLIC_CONNS)) { + return new Boolean(_settings.getSetting(SettingsManager.SETTING_ALWAYS_ALLOW_PUBLIC_CONN) == SettingsManager.VALUE_ENABLED); + } else { + return UNDEFINED; + } + } +} diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/users/BBMPlatformUser.java b/api/bbm/src/main/java/blackberry/bbm/platform/users/BBMPlatformUser.java index 2a73463..e8922b7 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/users/BBMPlatformUser.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/users/BBMPlatformUser.java @@ -23,14 +23,16 @@ public class BBMPlatformUser extends Scriptable { - public static final String FIELD_DISPLAY_PIC = "displayPicture"; - public static final String FIELD_DISPLAY_NAME = "displayName"; - public static final String FIELD_PERSONAL_MSG = "personalMessage"; - public static final String FIELD_STATUS = "status"; - public static final String FIELD_STATUS_MSG = "statusMessage"; - public static final String FIELD_HANDLE = "handle"; - public static final String FIELD_PPID = "ppid"; - public static final String FIELD_TYPE = "type"; + public static final String FIELD_DISPLAY_PIC = "displayPicture"; + public static final String FIELD_DISPLAY_NAME = "displayName"; + public static final String FIELD_PERSONAL_MSG = "personalMessage"; + public static final String FIELD_STATUS = "status"; + public static final String FIELD_STATUS_MSG = "statusMessage"; + public static final String FIELD_HANDLE = "handle"; + public static final String FIELD_PPID = "ppid"; + public static final String FIELD_TYPE = "type"; + public static final String FIELD_APP_VERSION = "appVersion"; + public static final String FIELD_BBM_SDK_VERSION = "bbmsdkVersion"; public static final String STATUS_STR_AVAILABLE = "available"; public static final String STATUS_STR_BUSY = "busy"; @@ -57,6 +59,10 @@ public Object getField(String name) throws Exception { return BBMPlatformUser.statusToString(_presence.getStatus()); } else if(name.equals(BBMPlatformUser.FIELD_STATUS_MSG)) { return _presence.getStatusMessage(); + } else if(name.equals(BBMPlatformUser.FIELD_APP_VERSION)) { + return _presence.getAppVersion(); + } else if(name.equals(BBMPlatformUser.FIELD_BBM_SDK_VERSION)) { + return new Integer(_presence.getBBMSDKVersion()); } else if(name.equals(BBMPlatformUser.FIELD_TYPE)) { return "BBM"; } else if(name.equals(BBMPlatformUser.FIELD_HANDLE)) { diff --git a/api/bbm/src/main/java/blackberry/bbm/platform/users/UsersNamespace.java b/api/bbm/src/main/java/blackberry/bbm/platform/users/UsersNamespace.java index 7d2d4c6..b2daaea 100644 --- a/api/bbm/src/main/java/blackberry/bbm/platform/users/UsersNamespace.java +++ b/api/bbm/src/main/java/blackberry/bbm/platform/users/UsersNamespace.java @@ -17,6 +17,7 @@ import net.rim.blackberry.api.bbm.platform.BBMPlatformContext; import net.rim.blackberry.api.bbm.platform.io.BBMPlatformConnection; +import net.rim.blackberry.api.bbm.platform.io.BBMPlatformData; import net.rim.blackberry.api.bbm.platform.io.IOErrorCode; import net.rim.blackberry.api.bbm.platform.profile.BBMInvitationRequest; import net.rim.blackberry.api.bbm.platform.profile.BBMPlatformContact; @@ -52,6 +53,8 @@ public class UsersNamespace extends Scriptable { private static final String FUNC_SEND_FILE = "sendFile"; private static final String FIELD_CONTACTS_WITH_APP = "contactsWithApp"; private static final String EVENT_ON_UPDATE = "onupdate"; + private static final String FUNC_SHARE_CONTENT = "shareContent"; + public static final String EVENT_ON_SHARE_CONTENT = "onsharecontent"; private static UsersNamespace instance; @@ -62,6 +65,7 @@ public class UsersNamespace extends Scriptable { private UsersNamespace() { _wFields = new ScriptableFieldManager(); _wFields.addField(EVENT_ON_UPDATE); + _wFields.addField(EVENT_ON_SHARE_CONTENT); } public static UsersNamespace getInstance() { @@ -98,6 +102,8 @@ public Object getField(String name) throws Exception { return new InviteToBBMConnFunction(); } else if(name.equals(FUNC_SEND_FILE)) { return new SendFileFunction(); + } else if(name.equals(FUNC_SHARE_CONTENT)) { + return new ShareContentFunction(); } else if(_wFields.hasField(name)) { return _wFields.getField(name); } else { @@ -485,6 +491,80 @@ protected FunctionSignature[] getFunctionSignatures() { }; } } // SendFileFunction + + private static class ShareContentFunction extends ScriptableFunctionBase { + + protected Object execute(Object thiz, Object[] args) throws Exception { + final String content = (String) args[0]; + final String description = (String) args[1]; + final ScriptableFunction onComplete = (ScriptableFunction) args[2]; + final Object options; + if(args.length >= 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(); 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..dd7329d --- /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(); + + type[ i ] = ( (String) choice.getField( "type" ) ).equals( "group" ) ? POPUP_ITEM_TYPE_GROUP + : POPUP_ITEM_TYPE_OPTION; + + canSelect = (type[ i ] != POPUP_ITEM_TYPE_GROUP) && (allowMultiple || !firstSelected); + selected[ i ] = canSelect && enabled[ i ] && ( (Boolean) choice.getField( "selected" ) ).booleanValue(); + firstSelected = firstSelected || selected[ i ]; + } + } 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..2d69752 --- /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( _listItems[ index ].getIndex() ) ); + } + } + + 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 0000000..16f0b0d Binary files /dev/null and b/api/dialog/src/main/java/blackberry/ui/dialog/select/box-empty.png differ 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 0000000..6d2a1d0 Binary files /dev/null and b/api/dialog/src/main/java/blackberry/ui/dialog/select/chk-blue.png differ 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 0000000..531c8df Binary files /dev/null and b/api/dialog/src/main/java/blackberry/ui/dialog/select/chk-white.png differ 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; + } +} 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 6f67452..700008f 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 ); @@ -131,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/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/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(); } 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/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/framework/src/blackberry/web/widget/policy/WidgetPolicy.java b/framework/src/blackberry/web/widget/policy/WidgetPolicy.java index 6c1f4a9..4df07ca 100644 --- a/framework/src/blackberry/web/widget/policy/WidgetPolicy.java +++ b/framework/src/blackberry/web/widget/policy/WidgetPolicy.java @@ -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; } diff --git a/framework/src/js/navmode.js b/framework/src/js/navmode.js new file mode 100644 index 0000000..f1fb923 --- /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)})() diff --git a/framework/src/js/navmode_uncompressed.js b/framework/src/js/navmode_uncompressed.js new file mode 100644 index 0000000..12f917d --- /dev/null +++ b/framework/src/js/navmode_uncompressed.js @@ -0,0 +1,1451 @@ +/* + * 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++) { + if (focusables[i].tagName === "SELECT") { + if (!focusables[i].disabled) { + items.push(focusables[i]); + } + } else { + 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); +}()); 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/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( "\" " ); } 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 { 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 0000000..9cab3cf Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/wheel.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/YUIexamples.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/YUIexamples.js new file mode 100644 index 0000000..8ee8917 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/YUIexamples.js @@ -0,0 +1,32 @@ +//Create namespace: +YAHOO.namespace("yui.examples"); + +//Only instantiate logger stuff if the page has loaded in logger mode: +if((YAHOO.widget.LogReader)&&(YAHOO.util.Dom.get("loggerDiv"))) { + //Create Logger instance for example page: + YAHOO.yui.examples.exampleLogger = new YAHOO.widget.LogReader("loggerDiv"); + + //Logger comes up a bit more cleanly if its container has an approximate + //height and is visibility:hidden intil after init; + YAHOO.yui.examples.loggerInit = function() { + YAHOO.util.Dom.setStyle("loggerDiv", "height", "auto"); + YAHOO.util.Dom.setStyle("loggerDiv", "visibility", "visible"); + } + YAHOO.util.Event.onDOMReady(YAHOO.yui.examples.loggerInit); +} + +//instantiate buttons: +YAHOO.yui.examples.onLinkButtonsMarkupReady = function() { + //if the logger is in use, enable its button: + if (YAHOO.util.Dom.get("loggerLink")) { + var loggerButton = new YAHOO.widget.Button("loggerLink"); + } + + //if a new window button is present, initialize it: + if (YAHOO.util.Dom.get("newWindowLink")) { + var newWindowButton = new YAHOO.widget.Button("newWindowLink"); + } +} +//wait until loggerDiv is present; the window buttons will have loaded +//by then as well: +YAHOO.util.Event.onDOMReady(YAHOO.yui.examples.onLinkButtonsMarkupReady); \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/bg_hd.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/bg_hd.gif new file mode 100644 index 0000000..c10acba Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/bg_hd.gif differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.css new file mode 100644 index 0000000..5fcbdf3 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.css @@ -0,0 +1,190 @@ +/* Give syntax-highlighting textareas some height for unsupported browsers */ + +textarea.JScript, textarea.HTML, textarea.XML {height:10em;} + +/* Main style for the table */ + +.dp-highlighter { + width: 100%; + overflow: auto; + line-height: 100% !important; + margin:0 0 1em 0; +} + +.dp-highlighter table { + width:99% !important; + margin: 2px 0px 2px 0px !important; + border-collapse: collapse; + border-bottom: 2px solid #eee; + background-color: #fff; +} + +.dp-highlighter tbody.hide { display: none; } +.dp-highlighter tbody.show { display: table-row-group; _display: block; } + +.dp-highlighter td +{ + font-family: Courier New; + font-size: 11px; +} + +/* Styles for the tools */ + +.dp-highlighter .tools-corner { + background-color: #eee; + font-size: 9px; +} + +.dp-highlighter .tools { + background-color: #eee; + padding: 3px 8px 3px 10px; + border-bottom: 1px solid gray; + font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif; + color: silver; +} + +.dp-highlighter .tools-corner { + background-color: #eee; +} + +.dp-highlighter .tools a { + font-size: 9px; + color: gray; + text-decoration: none; +} + +.dp-highlighter .tools a:hover { + color: red; + text-decoration: underline; +} + +/* Gutter with line number */ + +.dp-highlighter .gutter { + padding-right: 5px; + padding-left: 10px; + width: 5px; + background-color: #eee; + border-right: 1px solid gray; + color: gray; + text-align: right; + vertical-align: top; +} + +/* Single line style */ + +.dp-highlighter .line1, .line2 { + padding-left: 10px; + /*border-bottom: 1px solid #F7F7F7;*/ + white-space:nowrap; +} + +.dp-highlighter .line2 { + /*background-color: #F7F7F7;*/ +} + +/* About dialog styles */ + +.dp-about { + background-color: #fff; + margin: 0px; +} + +.dp-about table { + width: 100%; + height: 100%; + font-size: 11px; + font-family: Tahoma, Verdana, Arial, sans-serif !important; +} + +.dp-about td { + padding: 10px; + vertical-align: top; +} + +.dp-about .copy { + border-bottom: 1px solid #ACA899; + height: 95%; +} + +.dp-about .title { + color: red; + font-weight: bold; +} + +.dp-about .para { + margin-bottom: 4px; +} + +.dp-about .footer { + background-color: #ECEADB; + border-top: 1px solid #fff; + text-align: right; +} + +.dp-about .close { + font-size: 11px; + font-family: Tahoma, Verdana, Arial, sans-serif !important; + background-color: #ECEADB; + width: 60px; + height: 22px; +} + +/* Language specific styles */ + +.dp-c {} +.dp-c .comment { color: green; } +.dp-c .string { color: blue; } +.dp-c .preprocessor { color: gray; } +.dp-c .keyword { color: blue; } +.dp-c .vars { color: #d00; } +/* +.dp-vb {} +.dp-vb .comment { color: green; } +.dp-vb .string { color: blue; } +.dp-vb .preprocessor { color: gray; } +.dp-vb .keyword { color: blue; } + +.dp-sql {} +.dp-sql .comment { color: green; } +.dp-sql .string { color: red; } +.dp-sql .keyword { color: blue; } +.dp-sql .func { color: #ff1493; } +.dp-sql .op { color: #808080; } +*/ +.dp-xml {} +.dp-xml .cdata { color: #ff1493; } +.dp-xml .comments { color: green; } +.dp-xml .tag { color: blue; } +.dp-xml .tag-name { color: black; font-weight: bold; } +.dp-xml .attribute { color: red; } +.dp-xml .attribute-value { color: blue; } +/* +.dp-delphi {} +.dp-delphi .comment { color: #008200; font-style: italic; } +.dp-delphi .string { color: blue; } +.dp-delphi .number { color: blue; } +.dp-delphi .directive { color: #008284; } +.dp-delphi .keyword { font-weight: bold; color: navy; } +.dp-delphi .vars { color: #000; } + +.dp-py {} +.dp-py .comment { color: green; } +.dp-py .string { color: red; } +.dp-py .docstring { color: brown; } +.dp-py .keyword { color: blue; font-weight: bold;} +.dp-py .builtins { color: #ff1493; } +.dp-py .magicmethods { color: #808080; } +.dp-py .exceptions { color: brown; } +.dp-py .types { color: brown; font-style: italic; } +.dp-py .commonlibs { color: #8A2BE2; font-style: italic; }*/ + + +.dp-css .keyword { color: red; } +.dp-css .value { color: #ff1493; } +.dp-css .comment { color: green; } +.dp-css .string { color: blue; } +.dp-css .preprocessor { color: gray; } +.dp-css .keyword { color: blue; } +.dp-css .vars { color: #d00; } +.dp-css .colors { font-weight: bold; } diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.js new file mode 100644 index 0000000..94ad098 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/dpSyntaxHighlighter.js @@ -0,0 +1,805 @@ +/** + * Code Syntax Highlighter. + * Version 1.3.0 + * Copyright (C) 2004 Alex Gorbatchev. + * http://www.dreamprojections.com/syntaxhighlighter/ + * + * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// create namespaces +// +var dp = { + sh : // dp.sh + { + Utils : {}, // dp.sh.Utils + Brushes : {}, // dp.sh.Brushes + Strings : {}, + Version : '1.3.0' + } +}; + +dp.sh.Strings = { + AboutDialog : '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 + // /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 0000000..6c61b95 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui-candy.jpg differ 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 0000000..5033ff5 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yui.gif differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yuiDistribution.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yuiDistribution.css new file mode 100644 index 0000000..e69de29 diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yuilib.jpg b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yuilib.jpg new file mode 100644 index 0000000..88b8255 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/assets/yuilib.jpg differ 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 0000000..fe2cd23 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/ajax-loader.gif differ 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 0000000..a1fe738 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/asc.gif differ 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 0000000..5f69f4e Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-h.png differ 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 0000000..658574a Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/back-v.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-h.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-h.png new file mode 100644 index 0000000..fea13b1 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-h.png differ 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 0000000..2efd664 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bar-v.png differ 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 0000000..9962889 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-h.gif differ 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 0000000..8e287cd Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/bg-v.gif differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/blankimage.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/blankimage.png new file mode 100644 index 0000000..b87bb24 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/blankimage.png differ 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 0000000..193028b Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check0.gif differ 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 0000000..7d9ceba Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check1.gif differ 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 0000000..1813175 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/check2.gif differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/colorpicker.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/colorpicker.css new file mode 100644 index 0000000..77ac7c1 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/colorpicker.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-picker-panel{background:#e3e3e3;border-color:#888}.yui-picker-panel .hd{background-color:#ccc;font-size:100%;line-height:100%;border:1px solid #e3e3e3;font-weight:bold;overflow:hidden;padding:6px;color:#000}.yui-picker-panel .bd{background:#e8e8e8;margin:1px;height:200px}.yui-picker-panel .ft{background:#e8e8e8;margin:1px;padding:1px}.yui-picker{position:relative}.yui-picker-hue-thumb{cursor:default;width:18px;height:18px;top:-8px;left:-2px;z-index:9;position:absolute}.yui-picker-hue-bg{-moz-outline:0;outline:0 none;position:absolute;left:200px;height:183px;width:14px;background:url(hue_bg.png) no-repeat;top:4px}.yui-picker-bg{-moz-outline:0;outline:0 none;position:absolute;top:4px;left:4px;height:182px;width:182px;background-color:#F00;background-image:url(picker_mask.png)}*html .yui-picker-bg{background-image:none;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='picker_mask.png',sizingMethod='scale')}.yui-picker-mask{position:absolute;z-index:1;top:0;left:0}.yui-picker-thumb{cursor:default;width:11px;height:11px;z-index:9;position:absolute;top:-4px;left:-4px}.yui-picker-swatch{position:absolute;left:240px;top:4px;height:60px;width:55px;border:1px solid #888}.yui-picker-websafe-swatch{position:absolute;left:304px;top:4px;height:24px;width:24px;border:1px solid #888}.yui-picker-controls{position:absolute;top:72px;left:226px;font:1em monospace}.yui-picker-controls .hd{background:transparent;border-width:0!important}.yui-picker-controls .bd{height:100px;border-width:0!important}.yui-picker-controls ul{float:left;padding:0 2px 0 0;margin:0}.yui-picker-controls li{padding:2px;list-style:none;margin:0}.yui-picker-controls input{font-size:.85em;width:2.4em}.yui-picker-hex-controls{clear:both;padding:2px}.yui-picker-hex-controls input{width:4.6em}.yui-picker-controls a{font:1em arial,helvetica,clean,sans-serif;display:block;*display:inline-block;padding:0;color:#000} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/container.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/container.css new file mode 100644 index 0000000..e4db6e3 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/container.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-overlay,.yui-panel-container{visibility:hidden;position:absolute;z-index:2}.yui-panel{position:relative}.yui-panel-container form{margin:0}.mask{z-index:1;display:none;position:absolute;top:0;left:0;right:0;bottom:0}.mask.block-scrollbars{overflow:auto}.masked select,.drag select,.hide-select select{_visibility:hidden}.yui-panel-container select{_visibility:inherit}.hide-scrollbars,.hide-scrollbars *{overflow:hidden}.hide-scrollbars select{display:none}.show-scrollbars{overflow:auto}.yui-panel-container.show-scrollbars,.yui-tt.show-scrollbars{overflow:visible}.yui-panel-container.show-scrollbars .underlay,.yui-tt.show-scrollbars .yui-tt-shadow{overflow:auto}.yui-panel-container.shadow .underlay.yui-force-redraw{padding-bottom:1px}.yui-effect-fade .underlay,.yui-effect-fade .yui-tt-shadow{display:none}.yui-tt-shadow{position:absolute}.yui-override-padding{padding:0!important}.yui-panel-container .container-close{overflow:hidden;text-indent:-10000em;text-decoration:none}.yui-overlay.yui-force-redraw,.yui-panel-container.yui-force-redraw{margin-bottom:1px}.yui-skin-sam .mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui-skin-sam .yui-panel-container{padding:0 1px;*padding:2px}.yui-skin-sam .yui-panel{position:relative;left:0;top:0;border-style:solid;border-width:1px 0;border-color:#808080;z-index:1;*border-width:1px;*zoom:1;_zoom:normal}.yui-skin-sam .yui-panel .hd,.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{border-style:solid;border-width:0 1px;border-color:#808080;margin:0 -1px;*margin:0;*border:0}.yui-skin-sam .yui-panel .hd{border-bottom:solid 1px #ccc}.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{background-color:#f2f2f2}.yui-skin-sam .yui-panel .hd{padding:0 10px;font-size:93%;line-height:2;*line-height:1.9;font-weight:bold;color:#000;background:url(sprite.png) repeat-x 0 -200px}.yui-skin-sam .yui-panel .bd{padding:10px}.yui-skin-sam .yui-panel .ft{border-top:solid 1px #808080;padding:5px 10px;font-size:77%}.yui-skin-sam .container-close{position:absolute;top:5px;right:6px;width:25px;height:15px;background:url(sprite.png) no-repeat 0 -300px;cursor:pointer}.yui-skin-sam .yui-panel-container .underlay{right:-1px;left:-1px}.yui-skin-sam .yui-panel-container.matte{padding:9px 10px;background-color:#fff}.yui-skin-sam .yui-panel-container.shadow{_padding:2px 4px 0 2px}.yui-skin-sam .yui-panel-container.shadow .underlay{position:absolute;top:2px;left:-3px;right:-3px;bottom:-3px;*top:4px;*left:-1px;*right:-1px;*bottom:-1px;_top:0;_left:0;_right:0;_bottom:0;_margin-top:3px;_margin-left:-1px;background-color:#000;opacity:.12;filter:alpha(opacity=12)}.yui-skin-sam .yui-dialog .ft{border-top:0;padding:0 10px 10px 10px;font-size:100%}.yui-skin-sam .yui-dialog .ft .button-group{display:block;text-align:right}.yui-skin-sam .yui-dialog .ft button.default{font-weight:bold}.yui-skin-sam .yui-dialog .ft span.default{border-color:#304369;background-position:0 -1400px}.yui-skin-sam .yui-dialog .ft span.default .first-child{border-color:#304369}.yui-skin-sam .yui-dialog .ft span.default button{color:#fff}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled{background-position:0 -1500px;border-color:#ccc}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled .first-child{border-color:#ccc}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled button{color:#a6a6a6}.yui-skin-sam .yui-simple-dialog .bd .yui-icon{background:url(sprite.png) no-repeat 0 0;width:16px;height:16px;margin-right:10px;float:left}.yui-skin-sam .yui-simple-dialog .bd span.blckicon{background-position:0 -1100px}.yui-skin-sam .yui-simple-dialog .bd span.alrticon{background-position:0 -1050px}.yui-skin-sam .yui-simple-dialog .bd span.hlpicon{background-position:0 -1150px}.yui-skin-sam .yui-simple-dialog .bd span.infoicon{background-position:0 -1200px}.yui-skin-sam .yui-simple-dialog .bd span.warnicon{background-position:0 -1900px}.yui-skin-sam .yui-simple-dialog .bd span.tipicon{background-position:0 -1250px}.yui-skin-sam .yui-tt .bd{position:relative;top:0;left:0;z-index:1;color:#000;padding:2px 5px;border-color:#d4c237 #A6982b #a6982b #A6982B;border-width:1px;border-style:solid;background-color:#ffee69}.yui-skin-sam .yui-tt.show-scrollbars .bd{overflow:auto}.yui-skin-sam .yui-tt-shadow{top:2px;right:-3px;left:-3px;bottom:-3px;background-color:#000}.yui-skin-sam .yui-tt-shadow-visible{opacity:.12;filter:alpha(opacity=12)} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/datatable.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/datatable.css new file mode 100644 index 0000000..91d07c3 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/datatable.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-skin-sam .yui-dt-mask{position:absolute;z-index:9500}.yui-dt-tmp{position:absolute;left:-9000px}.yui-dt-scrollable .yui-dt-bd{overflow:auto}.yui-dt-scrollable .yui-dt-hd{overflow:hidden;position:relative}.yui-dt-scrollable .yui-dt-bd thead tr,.yui-dt-scrollable .yui-dt-bd thead th{position:absolute;left:-1500px}.yui-dt-scrollable tbody{-moz-outline:0}.yui-skin-sam thead .yui-dt-sortable{cursor:pointer}.yui-skin-sam thead .yui-dt-draggable{cursor:move}.yui-dt-coltarget{position:absolute;z-index:999}.yui-dt-hd{zoom:1}th.yui-dt-resizeable .yui-dt-resizerliner{position:relative}.yui-dt-resizer{position:absolute;right:0;bottom:0;height:100%;cursor:e-resize;cursor:col-resize;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}.yui-dt-resizerproxy{visibility:hidden;position:absolute;z-index:9000;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}th.yui-dt-hidden .yui-dt-liner,td.yui-dt-hidden .yui-dt-liner,th.yui-dt-hidden .yui-dt-resizer{display:none}.yui-dt-editor,.yui-dt-editor-shim{position:absolute;z-index:9000}.yui-skin-sam .yui-dt table{margin:0;padding:0;font-family:arial;font-size:inherit;border-collapse:separate;*border-collapse:collapse;border-spacing:0;border:1px solid #7f7f7f}.yui-skin-sam .yui-dt thead{border-spacing:0}.yui-skin-sam .yui-dt caption{color:#000;font-size:85%;font-weight:normal;font-style:italic;line-height:1;padding:1em 0;text-align:center}.yui-skin-sam .yui-dt th{background:#d8d8da url(sprite.png) repeat-x 0 0}.yui-skin-sam .yui-dt th,.yui-skin-sam .yui-dt th a{font-weight:normal;text-decoration:none;color:#000;vertical-align:bottom}.yui-skin-sam .yui-dt th{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb}.yui-skin-sam .yui-dt tr.yui-dt-first td{border-top:1px solid #7f7f7f}.yui-skin-sam .yui-dt th .yui-dt-liner{white-space:nowrap}.yui-skin-sam .yui-dt-liner{margin:0;padding:0;padding:4px 10px 4px 10px}.yui-skin-sam .yui-dt-coltarget{width:5px;background-color:red}.yui-skin-sam .yui-dt td{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb;text-align:left}.yui-skin-sam .yui-dt-list td{border-right:0}.yui-skin-sam .yui-dt-resizer{width:6px}.yui-skin-sam .yui-dt-mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui-skin-sam .yui-dt-message{background-color:#FFF}.yui-skin-sam .yui-dt-scrollable table{border:0}.yui-skin-sam .yui-dt-scrollable .yui-dt-hd{border-left:1px solid #7f7f7f;border-top:1px solid #7f7f7f;border-right:1px solid #7f7f7f}.yui-skin-sam .yui-dt-scrollable .yui-dt-bd{border-left:1px solid #7f7f7f;border-bottom:1px solid #7f7f7f;border-right:1px solid #7f7f7f;background-color:#FFF}.yui-skin-sam .yui-dt-scrollable .yui-dt-data tr.yui-dt-last td{border-bottom:1px solid #7f7f7f}.yui-skin-sam th.yui-dt-asc,.yui-skin-sam th.yui-dt-desc{background:url(sprite.png) repeat-x 0 -100px}.yui-skin-sam th.yui-dt-sortable .yui-dt-label{margin-right:10px}.yui-skin-sam th.yui-dt-asc .yui-dt-liner{background:url(dt-arrow-up.png) no-repeat right}.yui-skin-sam th.yui-dt-desc .yui-dt-liner{background:url(dt-arrow-dn.png) no-repeat right}tbody .yui-dt-editable{cursor:pointer}.yui-dt-editor{text-align:left;background-color:#f2f2f2;border:1px solid #808080;padding:6px}.yui-dt-editor label{padding-left:4px;padding-right:6px}.yui-dt-editor .yui-dt-button{padding-top:6px;text-align:right}.yui-dt-editor .yui-dt-button button{background:url(sprite.png) repeat-x 0 0;border:1px solid #999;width:4em;height:1.8em;margin-left:6px}.yui-dt-editor .yui-dt-button button.yui-dt-default{background:url(sprite.png) repeat-x 0 -1400px;background-color:#5584e0;border:1px solid #304369;color:#FFF}.yui-dt-editor .yui-dt-button button:hover{background:url(sprite.png) repeat-x 0 -1300px;color:#000}.yui-dt-editor .yui-dt-button button:active{background:url(sprite.png) repeat-x 0 -1700px;color:#000}.yui-skin-sam tr.yui-dt-even{background-color:#FFF}.yui-skin-sam tr.yui-dt-odd{background-color:#edf5ff}.yui-skin-sam tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam tr.yui-dt-even td.yui-dt-desc{background-color:#edf5ff}.yui-skin-sam tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam tr.yui-dt-odd td.yui-dt-desc{background-color:#dbeaff}.yui-skin-sam .yui-dt-list tr.yui-dt-even{background-color:#FFF}.yui-skin-sam .yui-dt-list tr.yui-dt-odd{background-color:#FFF}.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-desc{background-color:#edf5ff}.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-desc{background-color:#edf5ff}.yui-skin-sam th.yui-dt-highlighted,.yui-skin-sam th.yui-dt-highlighted a{background-color:#b2d2ff}.yui-skin-sam tr.yui-dt-highlighted,.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-asc,.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-desc,.yui-skin-sam tr.yui-dt-even td.yui-dt-highlighted,.yui-skin-sam tr.yui-dt-odd td.yui-dt-highlighted{cursor:pointer;background-color:#b2d2ff}.yui-skin-sam .yui-dt-list th.yui-dt-highlighted,.yui-skin-sam .yui-dt-list th.yui-dt-highlighted a{background-color:#b2d2ff}.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted,.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-desc,.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-highlighted,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-highlighted{cursor:pointer;background-color:#b2d2ff}.yui-skin-sam th.yui-dt-selected,.yui-skin-sam th.yui-dt-selected a{background-color:#446cd7}.yui-skin-sam tr.yui-dt-selected td,.yui-skin-sam tr.yui-dt-selected td.yui-dt-asc,.yui-skin-sam tr.yui-dt-selected td.yui-dt-desc{background-color:#426fd9;color:#FFF}.yui-skin-sam tr.yui-dt-even td.yui-dt-selected,.yui-skin-sam tr.yui-dt-odd td.yui-dt-selected{background-color:#446cd7;color:#FFF}.yui-skin-sam .yui-dt-list th.yui-dt-selected,.yui-skin-sam .yui-dt-list th.yui-dt-selected a{background-color:#446cd7} +.yui-skin-sam .yui-dt-list tr.yui-dt-selected td,.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-desc{background-color:#426fd9;color:#FFF}.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-selected,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-selected{background-color:#446cd7;color:#FFF}.yui-skin-sam .yui-dt-paginator{display:block;margin:6px 0;white-space:nowrap}.yui-skin-sam .yui-dt-paginator .yui-dt-first,.yui-skin-sam .yui-dt-paginator .yui-dt-last,.yui-skin-sam .yui-dt-paginator .yui-dt-selected{padding:2px 6px}.yui-skin-sam .yui-dt-paginator a.yui-dt-first,.yui-skin-sam .yui-dt-paginator a.yui-dt-last{text-decoration:none}.yui-skin-sam .yui-dt-paginator .yui-dt-previous,.yui-skin-sam .yui-dt-paginator .yui-dt-next{display:none}.yui-skin-sam a.yui-dt-page{border:1px solid #cbcbcb;padding:2px 6px;text-decoration:none;background-color:#fff}.yui-skin-sam .yui-dt-selected{border:1px solid #fff;background-color:#fff} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/desc.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/desc.gif new file mode 100644 index 0000000..c114f29 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/desc.gif differ 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 0000000..85fda0b Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-dn.png differ 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 0000000..1c67431 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/dt-arrow-up.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-knob.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-knob.gif new file mode 100644 index 0000000..03feab3 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-knob.gif differ 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 0000000..3e9d420 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite-active.gif differ 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 0000000..02042fa Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/editor-sprite.gif differ 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 0000000..3ef7909 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/header_background.png differ 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 0000000..d9bcdeb Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/hue_bg.png differ 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 0000000..d6fce3c Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/layout_sprite.png differ 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 0000000..0bbf3bc Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/loading.gif differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/logger.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/logger.css new file mode 100644 index 0000000..bc5397e --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/logger.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-log{padding:1em;width:31em;background-color:#AAA;color:#000;border:1px solid black;font-family:monospace;font-size:77%;text-align:left;z-index:9000}.yui-skin-sam .yui-log-container{position:absolute;top:1em;right:1em}.yui-skin-sam .yui-log input{margin:0;padding:0;font-family:arial;font-size:100%;font-weight:normal}.yui-skin-sam .yui-log .yui-log-btns{position:relative;float:right;bottom:.25em}.yui-skin-sam .yui-log .yui-log-hd{margin-top:1em;padding:.5em;background-color:#575757}.yui-skin-sam .yui-log .yui-log-hd h4{margin:0;padding:0;font-size:108%;font-weight:bold;color:#FFF}.yui-skin-sam .yui-log .yui-log-bd{width:100%;height:20em;background-color:#FFF;border:1px solid gray;overflow:auto}.yui-skin-sam .yui-log p{margin:1px;padding:.1em}.yui-skin-sam .yui-log pre{margin:0;padding:0}.yui-skin-sam .yui-log pre.yui-log-verbose{white-space:pre-wrap;white-space:-moz-pre-wrap!important;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}.yui-skin-sam .yui-log .yui-log-ft{margin-top:.5em}.yui-skin-sam .yui-log .yui-log-ft .yui-log-sourcefilters{width:100%;border-top:1px solid #575757;margin-top:.75em;padding-top:.75em}.yui-skin-sam .yui-log .yui-log-filtergrp{margin-right:.5em}.yui-skin-sam .yui-log .info{background-color:#a7cc25}.yui-skin-sam .yui-log .warn{background-color:#f58516}.yui-skin-sam .yui-log .error{background-color:#e32f0b}.yui-skin-sam .yui-log .time{background-color:#a6c9d7}.yui-skin-sam .yui-log .window{background-color:#f2e886} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow-disabled.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow-disabled.png new file mode 100644 index 0000000..8cef2ab Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow-disabled.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow.png new file mode 100644 index 0000000..f03dfee Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu-button-arrow.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu.css new file mode 100644 index 0000000..744ef09 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menu.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 +*/ +.yuimenu{top:-999em;left:-999em;}.yuimenubar{position:static;}.yuimenu .yuimenu,.yuimenubar .yuimenu{position:absolute;}.yuimenubar li,.yuimenu li{list-style-type:none;}.yuimenubar ul,.yuimenu ul,.yuimenubar li,.yuimenu li,.yuimenu h6,.yuimenubar h6{margin:0;padding:0;}.yuimenuitemlabel,.yuimenubaritemlabel{text-align:left;white-space:nowrap;}.yuimenubar ul{*zoom:1;}.yuimenubar .yuimenu ul{*zoom:normal;}.yuimenubar>.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 0000000..030941c Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator.png differ 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 0000000..6c16122 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menubaritem_submenuindicator_disabled.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox.png new file mode 100644 index 0000000..1437a4f Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox_disabled.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox_disabled.png new file mode 100644 index 0000000..5d5b998 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_checkbox_disabled.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator.png new file mode 100644 index 0000000..ea4f660 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator.png differ 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 0000000..427d60a Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/menuitem_submenuindicator_disabled.png differ 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 0000000..f8d9193 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/picker_mask.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/profilerviewer.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/profilerviewer.css new file mode 100644 index 0000000..8b3bfb4 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/profilerviewer.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-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;} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/progressbar.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/progressbar.css new file mode 100644 index 0000000..b44a87d --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/progressbar.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-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} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/resize.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/resize.css new file mode 100644 index 0000000..e332fe9 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/resize.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-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;} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/simpleeditor.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/simpleeditor.css new file mode 100644 index 0000000..bf4016e --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/simpleeditor.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;} \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/skin.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/skin.css new file mode 100644 index 0000000..f3a6af6 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/skin.css @@ -0,0 +1,35 @@ +/* +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} +.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);} +.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} +.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;} +.yui-picker-panel{background:#e3e3e3;border-color:#888}.yui-picker-panel .hd{background-color:#ccc;font-size:100%;line-height:100%;border:1px solid #e3e3e3;font-weight:bold;overflow:hidden;padding:6px;color:#000}.yui-picker-panel .bd{background:#e8e8e8;margin:1px;height:200px}.yui-picker-panel .ft{background:#e8e8e8;margin:1px;padding:1px}.yui-picker{position:relative}.yui-picker-hue-thumb{cursor:default;width:18px;height:18px;top:-8px;left:-2px;z-index:9;position:absolute}.yui-picker-hue-bg{-moz-outline:0;outline:0 none;position:absolute;left:200px;height:183px;width:14px;background:url(hue_bg.png) no-repeat;top:4px}.yui-picker-bg{-moz-outline:0;outline:0 none;position:absolute;top:4px;left:4px;height:182px;width:182px;background-color:#F00;background-image:url(picker_mask.png)}*html .yui-picker-bg{background-image:none;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='picker_mask.png',sizingMethod='scale')}.yui-picker-mask{position:absolute;z-index:1;top:0;left:0}.yui-picker-thumb{cursor:default;width:11px;height:11px;z-index:9;position:absolute;top:-4px;left:-4px}.yui-picker-swatch{position:absolute;left:240px;top:4px;height:60px;width:55px;border:1px solid #888}.yui-picker-websafe-swatch{position:absolute;left:304px;top:4px;height:24px;width:24px;border:1px solid #888}.yui-picker-controls{position:absolute;top:72px;left:226px;font:1em monospace}.yui-picker-controls .hd{background:transparent;border-width:0!important}.yui-picker-controls .bd{height:100px;border-width:0!important}.yui-picker-controls ul{float:left;padding:0 2px 0 0;margin:0}.yui-picker-controls li{padding:2px;list-style:none;margin:0}.yui-picker-controls input{font-size:.85em;width:2.4em}.yui-picker-hex-controls{clear:both;padding:2px}.yui-picker-hex-controls input{width:4.6em}.yui-picker-controls a{font:1em arial,helvetica,clean,sans-serif;display:block;*display:inline-block;padding:0;color:#000} +.yui-overlay,.yui-panel-container{visibility:hidden;position:absolute;z-index:2}.yui-panel{position:relative}.yui-panel-container form{margin:0}.mask{z-index:1;display:none;position:absolute;top:0;left:0;right:0;bottom:0}.mask.block-scrollbars{overflow:auto}.masked select,.drag select,.hide-select select{_visibility:hidden}.yui-panel-container select{_visibility:inherit}.hide-scrollbars,.hide-scrollbars *{overflow:hidden}.hide-scrollbars select{display:none}.show-scrollbars{overflow:auto}.yui-panel-container.show-scrollbars,.yui-tt.show-scrollbars{overflow:visible}.yui-panel-container.show-scrollbars .underlay,.yui-tt.show-scrollbars .yui-tt-shadow{overflow:auto}.yui-panel-container.shadow .underlay.yui-force-redraw{padding-bottom:1px}.yui-effect-fade .underlay,.yui-effect-fade .yui-tt-shadow{display:none}.yui-tt-shadow{position:absolute}.yui-override-padding{padding:0!important}.yui-panel-container .container-close{overflow:hidden;text-indent:-10000em;text-decoration:none}.yui-overlay.yui-force-redraw,.yui-panel-container.yui-force-redraw{margin-bottom:1px}.yui-skin-sam .mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui-skin-sam .yui-panel-container{padding:0 1px;*padding:2px}.yui-skin-sam .yui-panel{position:relative;left:0;top:0;border-style:solid;border-width:1px 0;border-color:#808080;z-index:1;*border-width:1px;*zoom:1;_zoom:normal}.yui-skin-sam .yui-panel .hd,.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{border-style:solid;border-width:0 1px;border-color:#808080;margin:0 -1px;*margin:0;*border:0}.yui-skin-sam .yui-panel .hd{border-bottom:solid 1px #ccc}.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{background-color:#f2f2f2}.yui-skin-sam .yui-panel .hd{padding:0 10px;font-size:93%;line-height:2;*line-height:1.9;font-weight:bold;color:#000;background:url(sprite.png) repeat-x 0 -200px}.yui-skin-sam .yui-panel .bd{padding:10px}.yui-skin-sam .yui-panel .ft{border-top:solid 1px #808080;padding:5px 10px;font-size:77%}.yui-skin-sam .container-close{position:absolute;top:5px;right:6px;width:25px;height:15px;background:url(sprite.png) no-repeat 0 -300px;cursor:pointer}.yui-skin-sam .yui-panel-container .underlay{right:-1px;left:-1px}.yui-skin-sam .yui-panel-container.matte{padding:9px 10px;background-color:#fff}.yui-skin-sam .yui-panel-container.shadow{_padding:2px 4px 0 2px}.yui-skin-sam .yui-panel-container.shadow .underlay{position:absolute;top:2px;left:-3px;right:-3px;bottom:-3px;*top:4px;*left:-1px;*right:-1px;*bottom:-1px;_top:0;_left:0;_right:0;_bottom:0;_margin-top:3px;_margin-left:-1px;background-color:#000;opacity:.12;filter:alpha(opacity=12)}.yui-skin-sam .yui-dialog .ft{border-top:0;padding:0 10px 10px 10px;font-size:100%}.yui-skin-sam .yui-dialog .ft .button-group{display:block;text-align:right}.yui-skin-sam .yui-dialog .ft button.default{font-weight:bold}.yui-skin-sam .yui-dialog .ft span.default{border-color:#304369;background-position:0 -1400px}.yui-skin-sam .yui-dialog .ft span.default .first-child{border-color:#304369}.yui-skin-sam .yui-dialog .ft span.default button{color:#fff}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled{background-position:0 -1500px;border-color:#ccc}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled .first-child{border-color:#ccc}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled button{color:#a6a6a6}.yui-skin-sam .yui-simple-dialog .bd .yui-icon{background:url(sprite.png) no-repeat 0 0;width:16px;height:16px;margin-right:10px;float:left}.yui-skin-sam .yui-simple-dialog .bd span.blckicon{background-position:0 -1100px}.yui-skin-sam .yui-simple-dialog .bd span.alrticon{background-position:0 -1050px}.yui-skin-sam .yui-simple-dialog .bd span.hlpicon{background-position:0 -1150px}.yui-skin-sam .yui-simple-dialog .bd span.infoicon{background-position:0 -1200px}.yui-skin-sam .yui-simple-dialog .bd span.warnicon{background-position:0 -1900px}.yui-skin-sam .yui-simple-dialog .bd span.tipicon{background-position:0 -1250px}.yui-skin-sam .yui-tt .bd{position:relative;top:0;left:0;z-index:1;color:#000;padding:2px 5px;border-color:#d4c237 #A6982b #a6982b #A6982B;border-width:1px;border-style:solid;background-color:#ffee69}.yui-skin-sam .yui-tt.show-scrollbars .bd{overflow:auto}.yui-skin-sam .yui-tt-shadow{top:2px;right:-3px;left:-3px;bottom:-3px;background-color:#000}.yui-skin-sam .yui-tt-shadow-visible{opacity:.12;filter:alpha(opacity=12)} +.yui-skin-sam .yui-dt-mask{position:absolute;z-index:9500}.yui-dt-tmp{position:absolute;left:-9000px}.yui-dt-scrollable .yui-dt-bd{overflow:auto}.yui-dt-scrollable .yui-dt-hd{overflow:hidden;position:relative}.yui-dt-scrollable .yui-dt-bd thead tr,.yui-dt-scrollable .yui-dt-bd thead th{position:absolute;left:-1500px}.yui-dt-scrollable tbody{-moz-outline:0}.yui-skin-sam thead .yui-dt-sortable{cursor:pointer}.yui-skin-sam thead .yui-dt-draggable{cursor:move}.yui-dt-coltarget{position:absolute;z-index:999}.yui-dt-hd{zoom:1}th.yui-dt-resizeable .yui-dt-resizerliner{position:relative}.yui-dt-resizer{position:absolute;right:0;bottom:0;height:100%;cursor:e-resize;cursor:col-resize;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}.yui-dt-resizerproxy{visibility:hidden;position:absolute;z-index:9000;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}th.yui-dt-hidden .yui-dt-liner,td.yui-dt-hidden .yui-dt-liner,th.yui-dt-hidden .yui-dt-resizer{display:none}.yui-dt-editor,.yui-dt-editor-shim{position:absolute;z-index:9000}.yui-skin-sam .yui-dt table{margin:0;padding:0;font-family:arial;font-size:inherit;border-collapse:separate;*border-collapse:collapse;border-spacing:0;border:1px solid #7f7f7f}.yui-skin-sam .yui-dt thead{border-spacing:0}.yui-skin-sam .yui-dt caption{color:#000;font-size:85%;font-weight:normal;font-style:italic;line-height:1;padding:1em 0;text-align:center}.yui-skin-sam .yui-dt th{background:#d8d8da url(sprite.png) repeat-x 0 0}.yui-skin-sam .yui-dt th,.yui-skin-sam .yui-dt th a{font-weight:normal;text-decoration:none;color:#000;vertical-align:bottom}.yui-skin-sam .yui-dt th{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb}.yui-skin-sam .yui-dt tr.yui-dt-first td{border-top:1px solid #7f7f7f}.yui-skin-sam .yui-dt th .yui-dt-liner{white-space:nowrap}.yui-skin-sam .yui-dt-liner{margin:0;padding:0;padding:4px 10px 4px 10px}.yui-skin-sam .yui-dt-coltarget{width:5px;background-color:red}.yui-skin-sam .yui-dt td{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb;text-align:left}.yui-skin-sam .yui-dt-list td{border-right:0}.yui-skin-sam .yui-dt-resizer{width:6px}.yui-skin-sam .yui-dt-mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui-skin-sam .yui-dt-message{background-color:#FFF}.yui-skin-sam .yui-dt-scrollable table{border:0}.yui-skin-sam .yui-dt-scrollable .yui-dt-hd{border-left:1px solid #7f7f7f;border-top:1px solid #7f7f7f;border-right:1px solid #7f7f7f}.yui-skin-sam .yui-dt-scrollable .yui-dt-bd{border-left:1px solid #7f7f7f;border-bottom:1px solid #7f7f7f;border-right:1px solid #7f7f7f;background-color:#FFF}.yui-skin-sam .yui-dt-scrollable .yui-dt-data tr.yui-dt-last td{border-bottom:1px solid #7f7f7f}.yui-skin-sam th.yui-dt-asc,.yui-skin-sam th.yui-dt-desc{background:url(sprite.png) repeat-x 0 -100px}.yui-skin-sam th.yui-dt-sortable .yui-dt-label{margin-right:10px}.yui-skin-sam th.yui-dt-asc .yui-dt-liner{background:url(dt-arrow-up.png) no-repeat right}.yui-skin-sam th.yui-dt-desc .yui-dt-liner{background:url(dt-arrow-dn.png) no-repeat right}tbody .yui-dt-editable{cursor:pointer}.yui-dt-editor{text-align:left;background-color:#f2f2f2;border:1px solid #808080;padding:6px}.yui-dt-editor label{padding-left:4px;padding-right:6px}.yui-dt-editor .yui-dt-button{padding-top:6px;text-align:right}.yui-dt-editor .yui-dt-button button{background:url(sprite.png) repeat-x 0 0;border:1px solid #999;width:4em;height:1.8em;margin-left:6px}.yui-dt-editor .yui-dt-button button.yui-dt-default{background:url(sprite.png) repeat-x 0 -1400px;background-color:#5584e0;border:1px solid #304369;color:#FFF}.yui-dt-editor .yui-dt-button button:hover{background:url(sprite.png) repeat-x 0 -1300px;color:#000}.yui-dt-editor .yui-dt-button button:active{background:url(sprite.png) repeat-x 0 -1700px;color:#000}.yui-skin-sam tr.yui-dt-even{background-color:#FFF}.yui-skin-sam tr.yui-dt-odd{background-color:#edf5ff}.yui-skin-sam tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam tr.yui-dt-even td.yui-dt-desc{background-color:#edf5ff}.yui-skin-sam tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam tr.yui-dt-odd td.yui-dt-desc{background-color:#dbeaff}.yui-skin-sam .yui-dt-list tr.yui-dt-even{background-color:#FFF}.yui-skin-sam .yui-dt-list tr.yui-dt-odd{background-color:#FFF}.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-desc{background-color:#edf5ff}.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-desc{background-color:#edf5ff}.yui-skin-sam th.yui-dt-highlighted,.yui-skin-sam th.yui-dt-highlighted a{background-color:#b2d2ff}.yui-skin-sam tr.yui-dt-highlighted,.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-asc,.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-desc,.yui-skin-sam tr.yui-dt-even td.yui-dt-highlighted,.yui-skin-sam tr.yui-dt-odd td.yui-dt-highlighted{cursor:pointer;background-color:#b2d2ff}.yui-skin-sam .yui-dt-list th.yui-dt-highlighted,.yui-skin-sam .yui-dt-list th.yui-dt-highlighted a{background-color:#b2d2ff}.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted,.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-desc,.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-highlighted,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-highlighted{cursor:pointer;background-color:#b2d2ff}.yui-skin-sam th.yui-dt-selected,.yui-skin-sam th.yui-dt-selected a{background-color:#446cd7}.yui-skin-sam tr.yui-dt-selected td,.yui-skin-sam tr.yui-dt-selected td.yui-dt-asc,.yui-skin-sam tr.yui-dt-selected td.yui-dt-desc{background-color:#426fd9;color:#FFF}.yui-skin-sam tr.yui-dt-even td.yui-dt-selected,.yui-skin-sam tr.yui-dt-odd td.yui-dt-selected{background-color:#446cd7;color:#FFF}.yui-skin-sam .yui-dt-list th.yui-dt-selected,.yui-skin-sam .yui-dt-list th.yui-dt-selected a{background-color:#446cd7} +.yui-skin-sam .yui-dt-list tr.yui-dt-selected td,.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-desc{background-color:#426fd9;color:#FFF}.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-selected,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-selected{background-color:#446cd7;color:#FFF}.yui-skin-sam .yui-dt-paginator{display:block;margin:6px 0;white-space:nowrap}.yui-skin-sam .yui-dt-paginator .yui-dt-first,.yui-skin-sam .yui-dt-paginator .yui-dt-last,.yui-skin-sam .yui-dt-paginator .yui-dt-selected{padding:2px 6px}.yui-skin-sam .yui-dt-paginator a.yui-dt-first,.yui-skin-sam .yui-dt-paginator a.yui-dt-last{text-decoration:none}.yui-skin-sam .yui-dt-paginator .yui-dt-previous,.yui-skin-sam .yui-dt-paginator .yui-dt-next{display:none}.yui-skin-sam a.yui-dt-page{border:1px solid #cbcbcb;padding:2px 6px;text-decoration:none;background-color:#fff}.yui-skin-sam .yui-dt-selected{border:1px solid #fff;background-color:#fff} +.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-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;} +.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;} +.yui-skin-sam .yui-log{padding:1em;width:31em;background-color:#AAA;color:#000;border:1px solid black;font-family:monospace;font-size:77%;text-align:left;z-index:9000}.yui-skin-sam .yui-log-container{position:absolute;top:1em;right:1em}.yui-skin-sam .yui-log input{margin:0;padding:0;font-family:arial;font-size:100%;font-weight:normal}.yui-skin-sam .yui-log .yui-log-btns{position:relative;float:right;bottom:.25em}.yui-skin-sam .yui-log .yui-log-hd{margin-top:1em;padding:.5em;background-color:#575757}.yui-skin-sam .yui-log .yui-log-hd h4{margin:0;padding:0;font-size:108%;font-weight:bold;color:#FFF}.yui-skin-sam .yui-log .yui-log-bd{width:100%;height:20em;background-color:#FFF;border:1px solid gray;overflow:auto}.yui-skin-sam .yui-log p{margin:1px;padding:.1em}.yui-skin-sam .yui-log pre{margin:0;padding:0}.yui-skin-sam .yui-log pre.yui-log-verbose{white-space:pre-wrap;white-space:-moz-pre-wrap!important;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}.yui-skin-sam .yui-log .yui-log-ft{margin-top:.5em}.yui-skin-sam .yui-log .yui-log-ft .yui-log-sourcefilters{width:100%;border-top:1px solid #575757;margin-top:.75em;padding-top:.75em}.yui-skin-sam .yui-log .yui-log-filtergrp{margin-right:.5em}.yui-skin-sam .yui-log .info{background-color:#a7cc25}.yui-skin-sam .yui-log .warn{background-color:#f58516}.yui-skin-sam .yui-log .error{background-color:#e32f0b}.yui-skin-sam .yui-log .time{background-color:#a6c9d7}.yui-skin-sam .yui-log .window{background-color:#f2e886} +.yuimenu{top:-999em;left:-999em;}.yuimenubar{position:static;}.yuimenu .yuimenu,.yuimenubar .yuimenu{position:absolute;}.yuimenubar li,.yuimenu li{list-style-type:none;}.yuimenubar ul,.yuimenu ul,.yuimenubar li,.yuimenu li,.yuimenu h6,.yuimenubar h6{margin:0;padding:0;}.yuimenuitemlabel,.yuimenubaritemlabel{text-align:left;white-space:nowrap;}.yuimenubar ul{*zoom:1;}.yuimenubar .yuimenu ul{*zoom:normal;}.yuimenubar>.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 0000000..fa58c50 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-active.png differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-disabled.png b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-disabled.png new file mode 100644 index 0000000..0a6a82c Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-disabled.png differ 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 0000000..167d71e Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-focus.png differ 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 0000000..167d71e Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow-hover.png differ 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 0000000..b33a93f Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/split-button-arrow.png differ 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 0000000..73634d6 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.png differ 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 0000000..fff2c34 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/sprite.psd differ 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 0000000..0bbf3bc Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-loading.gif differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-sprite.gif b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-sprite.gif new file mode 100644 index 0000000..8fb3f01 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/treeview-sprite.gif differ 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 0000000..471c1a4 Binary files /dev/null and b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/wait.gif differ diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/yuitest.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/yuitest.css new file mode 100644 index 0000000..7cfa36b --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/assets/skins/sam/yuitest.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 +*/ + diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base-min.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base-min.css new file mode 100644 index 0000000..f71b9a5 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base-min.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 +*/ +body{margin:10px}h1{font-size:138.5%}h2{font-size:123.1%}h3{font-size:108%}h1,h2,h3{margin:1em 0}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold}optgroup{font-weight:normal}abbr,acronym{border-bottom:1px dotted #000;cursor:help}em{font-style:italic}del{text-decoration:line-through}blockquote,ul,ol,dl{margin:1em}ol,ul,dl{margin-left:2em}ol{list-style:decimal outside}ul{list-style:disc outside}dl dd{margin-left:1em}th,td{border:1px solid #000;padding:.5em}th{font-weight:bold;text-align:center}caption{margin-bottom:.5em;text-align:center}sup{vertical-align:super}sub{vertical-align:sub}p,fieldset,table,pre{margin-bottom:1em}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px}img{-ms-interpolation-mode:bicubic} \ No newline at end of file diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base.css b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base.css new file mode 100644 index 0000000..557c75e --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/base/base.css @@ -0,0 +1,137 @@ +/* +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 Base + * @module base + * @namespace yui- + * @requires reset, fonts +*/ + +body { + /* For breathing room between content and viewport. */ + margin:10px; +} + +h1 { + /* 18px via YUI Fonts CSS foundation. */ + font-size: 138.5%; +} + +h2 { + /* 16px via YUI Fonts CSS foundation. */ + font-size: 123.1%; +} + +h3 { + /* 14px via YUI Fonts CSS foundation. */ + font-size: 108%; +} + +h1,h2,h3 { + /* Top & bottom margin based on font size. */ + margin: 1em 0; +} + +h1,h2,h3,h4,h5,h6,strong,dt { + /* Bringing boldness back to headers and the strong element. */ + font-weight: bold; +} +optgroup { + font-weight:normal; +} + +abbr,acronym { + /* Indicating to users that more info is available. */ + border-bottom: 1px dotted #000; + cursor: help; +} + +em { + /* Bringing italics back to the em element. */ + font-style: italic; +} + +del { + /* Striking deleted phrases. */ + text-decoration: line-through; +} + +blockquote,ul,ol,dl { + /* Giving blockquotes and lists room to breath. */ + margin: 1em; +} + +ol,ul,dl { + /* Bringing lists on to the page with breathing room. */ + margin-left: 2em; +} + +ol { + /* Giving OL's LIs generated numbers. */ + list-style: decimal outside; +} + +ul { + /* Giving UL's LIs generated disc markers. */ + list-style: disc outside; +} + +dl dd { + /* Giving DD default indent. */ + margin-left: 1em; +} + +th,td { + /* Borders and padding to make the table readable. */ + border: 1px solid #000; + padding: .5em; +} + +th { + /* Distinguishing table headers from data cells. */ + font-weight: bold; + text-align: center; +} + +caption { + /* Coordinated margin to match cell's padding. */ + margin-bottom: .5em; + /* Centered so it doesn't blend in to other content. */ + text-align: center; +} + +sup { + /* to preserve line-height and selector appearance */ + vertical-align: super; +} + +sub { + /* to preserve line-height and selector appearance */ + vertical-align: sub; +} + +p, +fieldset, +table, +pre { + /* So things don't run into each other. */ + margin-bottom: 1em; +} +/* Opera requires 1px of padding to render with contemporary native chrome */ +button, +input[type="checkbox"], +input[type="radio"], +input[type="reset"], +input[type="submit"] { + padding:1px; +} + +/* make IE scale images properly */ +/* see http://code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ */ + img { + -ms-interpolation-mode:bicubic; +} diff --git a/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-debug.js b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-debug.js new file mode 100644 index 0000000..02afc59 --- /dev/null +++ b/yui-tests/NavModeSmokeTestYUI2.0/yui2.9.0/build/dom/dom-debug.js @@ -0,0 +1,1885 @@ +/* +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 dom module provides helper methods for manipulating Dom elements. + * @module dom + * + */ + +(function() { + // for use with generateId (global to save state if Dom is overwritten) + YAHOO.env._id_counter = YAHOO.env._id_counter || 0; + + // internal shorthand + var Y = YAHOO.util, + lang = YAHOO.lang, + UA = YAHOO.env.ua, + trim = YAHOO.lang.trim, + propertyCache = {}, // for faster hyphen converts + reCache = {}, // cache className regexes + RE_TABLE = /^t(?:able|d|h)$/i, // for _calcBorders + RE_COLOR = /color$/i, + + // DOM aliases + document = window.document, + documentElement = document.documentElement, + + // string constants + OWNER_DOCUMENT = 'ownerDocument', + DEFAULT_VIEW = 'defaultView', + DOCUMENT_ELEMENT = 'documentElement', + COMPAT_MODE = 'compatMode', + OFFSET_LEFT = 'offsetLeft', + OFFSET_TOP = 'offsetTop', + OFFSET_PARENT = 'offsetParent', + PARENT_NODE = 'parentNode', + NODE_TYPE = 'nodeType', + TAG_NAME = 'tagName', + SCROLL_LEFT = 'scrollLeft', + SCROLL_TOP = 'scrollTop', + GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect', + GET_COMPUTED_STYLE = 'getComputedStyle', + CURRENT_STYLE = 'currentStyle', + CSS1_COMPAT = 'CSS1Compat', + _BACK_COMPAT = 'BackCompat', + _CLASS = 'class', // underscore due to reserved word + CLASS_NAME = 'className', + EMPTY = '', + SPACE = ' ', + C_START = '(?:^|\\s)', + C_END = '(?= |$)', + G = 'g', + POSITION = 'position', + FIXED = 'fixed', + RELATIVE = 'relative', + LEFT = 'left', + TOP = 'top', + MEDIUM = 'medium', + BORDER_LEFT_WIDTH = 'borderLeftWidth', + BORDER_TOP_WIDTH = 'borderTopWidth', + + // brower detection + isOpera = UA.opera, + isSafari = UA.webkit, + isGecko = UA.gecko, + isIE = UA.ie; + + /** + * Provides helper methods for DOM elements. + * @namespace YAHOO.util + * @class Dom + * @requires yahoo, event + */ + Y.Dom = { + CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8 + 'for': 'htmlFor', + 'class': CLASS_NAME + } : { // w3c + 'htmlFor': 'for', + 'className': _CLASS + }, + + DOT_ATTRIBUTES: { + checked: true + }, + + /** + * Returns an HTMLElement reference. + * @method get + * @param {String | HTMLElement |Array} el Accepts a string to use as an ID for getting a DOM reference, an actual DOM reference, or an Array of IDs and/or HTMLElements. + * @return {HTMLElement | Array} A DOM reference to an HTML element or an array of HTMLElements. + */ + get: function(el) { + var id, nodes, c, i, len, attr, ret = null; + + if (el) { + if (typeof el == 'string' || typeof el == 'number') { // id + id = el + ''; + el = document.getElementById(el); + attr = (el) ? el.attributes : null; + if (el && attr && attr.id && attr.id.value === id) { // IE: avoid false match on "name" attribute + return el; + } else if (el && document.all) { // filter by name + el = null; + nodes = document.all[id]; + if (nodes && nodes.length) { + for (i = 0, len = nodes.length; i < len; ++i) { + if (nodes[i].id === id) { + return nodes[i]; + } + } + } + } + } else if (Y.Element && el instanceof Y.Element) { + el = el.get('element'); + } else if (!el.nodeType && 'length' in el) { // array-like + c = []; + for (i = 0, len = el.length; i < len; ++i) { + c[c.length] = Y.Dom.get(el[i]); + } + + el = c; + } + + ret = el; + } + + return ret; + }, + + getComputedStyle: function(el, property) { + if (window[GET_COMPUTED_STYLE]) { + return el[OWNER_DOCUMENT][DEFAULT_VIEW][GET_COMPUTED_STYLE](el, null)[property]; + } else if (el[CURRENT_STYLE]) { + return Y.Dom.IE_ComputedStyle.get(el, property); + } + }, + + /** + * Normalizes currentStyle and ComputedStyle. + * @method getStyle + * @param {String | HTMLElement |Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. + * @param {String} property The style property whose value is returned. + * @return {String | Array} The current value of the style property for the element(s). + */ + getStyle: function(el, property) { + return Y.Dom.batch(el, Y.Dom._getStyle, property); + }, + + // branching at load instead of runtime + _getStyle: function() { + if (window[GET_COMPUTED_STYLE]) { // W3C DOM method + return function(el, property) { + property = (property === 'float') ? property = 'cssFloat' : + Y.Dom._toCamel(property); + + var value = el.style[property], + computed; + + if (!value) { + computed = el[OWNER_DOCUMENT][DEFAULT_VIEW][GET_COMPUTED_STYLE](el, null); + if (computed) { // test computed before touching for safari + value = computed[property]; + } + } + + return value; + }; + } else if (documentElement[CURRENT_STYLE]) { + return function(el, property) { + var value; + + switch(property) { + case 'opacity' :// IE opacity uses filter + value = 100; + try { // will error if no DXImageTransform + value = el.filters['DXImageTransform.Microsoft.Alpha'].opacity; + + } catch(e) { + try { // make sure its in the document + value = el.filters('alpha').opacity; + } catch(err) { + YAHOO.log('getStyle: IE filter failed', + 'error', 'Dom'); + } + } + return value / 100; + case 'float': // fix reserved word + property = 'styleFloat'; // fall through + default: + property = Y.Dom._toCamel(property); + value = el[CURRENT_STYLE] ? el[CURRENT_STYLE][property] : null; + return ( el.style[property] || value ); + } + }; + } + }(), + + /** + * Wrapper for setting style properties of HTMLElements. Normalizes "opacity" across modern browsers. + * @method setStyle + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. + * @param {String} property The style property to be set. + * @param {String} val The value to apply to the given property. + */ + setStyle: function(el, property, val) { + Y.Dom.batch(el, Y.Dom._setStyle, { prop: property, val: val }); + }, + + _setStyle: function() { + if (!window.getComputedStyle && document.documentElement.currentStyle) { + return function(el, args) { + var property = Y.Dom._toCamel(args.prop), + val = args.val; + + if (el) { + switch (property) { + case 'opacity': + // remove filter if unsetting or full opacity + if (val === '' || val === null || val === 1) { + el.style.removeAttribute('filter'); + } else if ( lang.isString(el.style.filter) ) { // in case not appended + el.style.filter = 'alpha(opacity=' + val * 100 + ')'; + + if (!el[CURRENT_STYLE] || !el[CURRENT_STYLE].hasLayout) { + el.style.zoom = 1; // when no layout or cant tell + } + } + break; + case 'float': + property = 'styleFloat'; + default: + el.style[property] = val; + } + } else { + YAHOO.log('element ' + el + ' is undefined', 'error', 'Dom'); + } + }; + } else { + return function(el, args) { + var property = Y.Dom._toCamel(args.prop), + val = args.val; + if (el) { + if (property == 'float') { + property = 'cssFloat'; + } + el.style[property] = val; + } else { + YAHOO.log('element ' + el + ' is undefined', 'error', 'Dom'); + } + }; + } + + }(), + + /** + * Gets the current position of an element based on page coordinates. + * Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). + * @method getXY + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM + * reference, or an Array of IDs and/or HTMLElements + * @return {Array} The XY position of the element(s) + */ + getXY: function(el) { + return Y.Dom.batch(el, Y.Dom._getXY); + }, + + _canPosition: function(el) { + return ( Y.Dom._getStyle(el, 'display') !== 'none' && Y.Dom._inDoc(el) ); + }, + + _getXY: function(node) { + var scrollLeft, scrollTop, box, doc, + clientTop, clientLeft, + round = Math.round, // TODO: round? + xy = false; + + if (Y.Dom._canPosition(node)) { + box = node[GET_BOUNDING_CLIENT_RECT](); + doc = node[OWNER_DOCUMENT]; + scrollLeft = Y.Dom.getDocumentScrollLeft(doc); + scrollTop = Y.Dom.getDocumentScrollTop(doc); + xy = [box[LEFT], box[TOP]]; + + // remove IE default documentElement offset (border) + if (clientTop || clientLeft) { + xy[0] -= clientLeft; + xy[1] -= clientTop; + } + + if ((scrollTop || scrollLeft)) { + xy[0] += scrollLeft; + xy[1] += scrollTop; + } + + // gecko may return sub-pixel (non-int) values + xy[0] = round(xy[0]); + xy[1] = round(xy[1]); + } else { + YAHOO.log('getXY failed: element not positionable (either not in a document or not displayed)', 'error', 'Dom'); + } + + return xy; + }, + + /** + * Gets the current X position of an element based on page coordinates. The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). + * @method getX + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements + * @return {Number | Array} The X position of the element(s) + */ + getX: function(el) { + var f = function(el) { + return Y.Dom.getXY(el)[0]; + }; + + return Y.Dom.batch(el, f, Y.Dom, true); + }, + + /** + * Gets the current Y position of an element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). + * @method getY + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements + * @return {Number | Array} The Y position of the element(s) + */ + getY: function(el) { + var f = function(el) { + return Y.Dom.getXY(el)[1]; + }; + + return Y.Dom.batch(el, f, Y.Dom, true); + }, + + /** + * Set the position of an html element in page coordinates, regardless of how the element is positioned. + * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). + * @method setXY + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements + * @param {Array} pos Contains X & Y values for new position (coordinates are page-based) + * @param {Boolean} noRetry By default we try and set the position a second time if the first fails + */ + setXY: function(el, pos, noRetry) { + Y.Dom.batch(el, Y.Dom._setXY, { pos: pos, noRetry: noRetry }); + }, + + _setXY: function(node, args) { + var pos = Y.Dom._getStyle(node, POSITION), + setStyle = Y.Dom.setStyle, + xy = args.pos, + noRetry = args.noRetry, + + delta = [ // assuming pixels; if not we will have to retry + parseInt( Y.Dom.getComputedStyle(node, LEFT), 10 ), + parseInt( Y.Dom.getComputedStyle(node, TOP), 10 ) + ], + + currentXY, + newXY; + + currentXY = Y.Dom._getXY(node); + + if (!xy || currentXY === false) { // has to be part of doc to have xy + YAHOO.log('xy failed: node not available', 'error', 'Node'); + return false; + } + + if (pos == 'static') { // default to relative + pos = RELATIVE; + setStyle(node, POSITION, pos); + } + + if ( isNaN(delta[0]) ) {// in case of 'auto' + delta[0] = (pos == RELATIVE) ? 0 : node[OFFSET_LEFT]; + } + if ( isNaN(delta[1]) ) { // in case of 'auto' + delta[1] = (pos == RELATIVE) ? 0 : node[OFFSET_TOP]; + } + + if (xy[0] !== null) { // from setX + setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px'); + } + + if (xy[1] !== null) { // from setY + setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px'); + } + + if (!noRetry) { + newXY = Y.Dom._getXY(node); + + // if retry is true, try one more time if we miss + if ( (xy[0] !== null && newXY[0] != xy[0]) || + (xy[1] !== null && newXY[1] != xy[1]) ) { + Y.Dom._setXY(node, { pos: xy, noRetry: true }); + } + } + + YAHOO.log('setXY setting position to ' + xy, 'info', 'Node'); + }, + + /** + * Set the X position of an html element in page coordinates, regardless of how the element is positioned. + * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). + * @method setX + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. + * @param {Int} x The value to use as the X coordinate for the element(s). + */ + setX: function(el, x) { + Y.Dom.setXY(el, [x, null]); + }, + + /** + * Set the Y position of an html element in page coordinates, regardless of how the element is positioned. + * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). + * @method setY + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. + * @param {Int} x To use as the Y coordinate for the element(s). + */ + setY: function(el, y) { + Y.Dom.setXY(el, [null, y]); + }, + + /** + * Returns the region position of the given element. + * The element must be part of the DOM tree to have a region (display:none or elements not appended return false). + * @method getRegion + * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. + * @return {Region | Array} A Region or array of Region instances containing "top, left, bottom, right" member data. + */ + getRegion: function(el) { + var f = function(el) { + var region = false; + if ( Y.Dom._canPosition(el) ) { + region = Y.Region.getRegion(el); + YAHOO.log('getRegion returning ' + region, 'info', 'Dom'); + } else { + YAHOO.log('getRegion failed: element not positionable (either not in a document or not displayed)', 'error', 'Dom'); + } + + return region; + }; + + return Y.Dom.batch(el, f, Y.Dom, true); + }, + + /** + * Returns the width of the client (viewport). + * @method getClientWidth + * @deprecated Now using getViewportWidth. This interface left intact for back compat. + * @return {Int} The width of the viewable area of the page. + */ + getClientWidth: function() { + return Y.Dom.getViewportWidth(); + }, + + /** + * Returns the height of the client (viewport). + * @method getClientHeight + * @deprecated Now using getViewportHeight. This interface left intact for back compat. + * @return {Int} The height of the viewable area of the page. + */ + getClientHeight: function() { + return Y.Dom.getViewportHeight(); + }, + + /** + * Returns an array of HTMLElements with the given class. + * 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 getElementsByClassName + * @param {String} className The class name to match against + * @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. + * This element is not included in the className scan. + * @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} An array of elements that have the given class name + */ + getElementsByClassName: function(className, tag, root, apply, o, overrides) { + tag = tag || '*'; + root = (root) ? Y.Dom.get(root) : null || document; + if (!root) { + return []; + } + + var nodes = [], + elements = root.getElementsByTagName(tag), + hasClass = Y.Dom.hasClass; + + for (var i = 0, len = elements.length; i < len; ++i) { + if ( hasClass(elements[i], className) ) { + nodes[nodes.length] = elements[i]; + } + } + + if (apply) { + Y.Dom.batch(nodes, apply, o, overrides); + } + + return nodes; + }, + + /** + * Determines whether an HTMLElement has the given className. + * @method hasClass + * @param {String | HTMLElement | Array} el The element or collection to test + * @param {String | RegExp} className the class name to search for, or a regular + * expression to match against + * @return {Boolean | Array} A boolean value or array of boolean values + */ + hasClass: function(el, className) { + return Y.Dom.batch(el, Y.Dom._hasClass, className); + }, + + _hasClass: function(el, className) { + var ret = false, + current; + + if (el && className) { + current = Y.Dom._getAttribute(el, CLASS_NAME) || EMPTY; + if (current) { // convert line breaks, tabs and other delims to spaces + current = current.replace(/\s+/g, SPACE); + } + + if (className.exec) { + ret = className.test(current); + } else { + ret = className && (SPACE + current + SPACE). + indexOf(SPACE + className + SPACE) > -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("