(childRefs.size());
+ for (ChildAssociationRef childRef : childRefs)
+ {
+ refs.add(childRef.getChildRef());
+ }
+
+ return refs;
+ }
+
+ private static CategoryService getCategoryService(FacesContext context)
+ {
+ CategoryService service = Repository.getServiceRegistry(context).getCategoryService();
+ if (service == null)
+ {
+ throw new IllegalStateException("Unable to obtain CategoryService bean reference.");
+ }
+
+ return service;
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java
index 21ff4f548a..5fada356b6 100644
--- a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java
+++ b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2010 Alfresco Software Limited.
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -423,6 +423,8 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
UIActionLink browseAction = aquireAction(
context, mainStore, username, ACT_SANDBOX_ICON, WebResources.IMAGE_USERSANDBOX_32,
"#{AVMBrowseBean.setupSandboxAction}", "browseSandbox");
+ browseAction.setTooltip(Application.getMessage(context, ACT_SANDBOX_BROWSE) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
+
browseAction.setShowLink(false);
Utils.encodeRecursive(context, browseAction);
out.write("");
@@ -446,31 +448,36 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
// Direct actions for a sandbox...
// Browse Sandbox
- Utils.encodeRecursive(context, aquireAction(
- context, mainStore, username, ACT_SANDBOX_BROWSE, "/images/icons/space_small.gif",
- "#{AVMBrowseBean.setupSandboxAction}", "browseSandbox"));
+ UIActionLink action = aquireAction(context, mainStore, username, ACT_SANDBOX_BROWSE, "/images/icons/space_small.gif", "#{AVMBrowseBean.setupSandboxAction}", "browseSandbox");
+ action.setTooltip(Application.getMessage(context, ACT_SANDBOX_BROWSE) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
+
+ Utils.encodeRecursive(context, action);
out.write(" | ");
// Preview Website
String websiteUrl = AVMUtil.getPreviewURI(mainStore, JNDIConstants.DIR_DEFAULT_WWW_APPBASE + '/' + getWebapp());
Map requestMap = context.getExternalContext().getRequestMap();
requestMap.put(REQUEST_PREVIEW_REF, websiteUrl);
- Utils.encodeRecursive(context, aquireAction(
- context, mainStore, username, ACT_SANDBOX_PREVIEW, "/images/icons/preview_website.gif",
- null, null, "#{" + REQUEST_PREVIEW_REF + "}", null));
+
+ action = aquireAction(context, mainStore, username, ACT_SANDBOX_PREVIEW, "/images/icons/preview_website.gif", null, null, "#{" + REQUEST_PREVIEW_REF + "}", null);
+ action.setTooltip(Application.getMessage(context, ACT_SANDBOX_PREVIEW) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
+
+ Utils.encodeRecursive(context, action);
requestMap.remove(REQUEST_PREVIEW_REF);
out.write(" | ");
// Submit All Items
- Utils.encodeRecursive(context, aquireAction(
- context, mainStore, username, ACT_SANDBOX_SUBMITALL, "/images/icons/submit_all.gif",
- "#{AVMBrowseBean.setupAllItemsAction}", "dialog:submitSandboxItems"));
+ action = aquireAction(context, mainStore, username, ACT_SANDBOX_SUBMITALL, "/images/icons/submit_all.gif", "#{AVMBrowseBean.setupAllItemsAction}", "dialog:submitSandboxItems");
+ action.setTooltip(Application.getMessage(context, ACT_SANDBOX_SUBMITALL) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
+
+ Utils.encodeRecursive(context, action);
out.write(" | ");
// Revert All Items
- Utils.encodeRecursive(context, aquireAction(
- context, mainStore, username, ACT_SANDBOX_REVERTALL, "/images/icons/revert_all.gif",
- "#{AVMBrowseBean.setupAllItemsAction}", "dialog:revertAllItems"));
+ action = aquireAction(context, mainStore, username, ACT_SANDBOX_REVERTALL, "/images/icons/revert_all.gif", "#{AVMBrowseBean.setupAllItemsAction}", "dialog:revertAllItems");
+ action.setTooltip(Application.getMessage(context, ACT_SANDBOX_REVERTALL) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
+
+ Utils.encodeRecursive(context, action);
out.write(" | ");
// More Actions menu
@@ -479,6 +486,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
{
// create the menu, then the actions
menu = createMenu(context, mainStore);
+ menu.setTooltip(Application.getMessage(context, "more_actions") + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
// add the menu to this component
this.getChildren().add(menu);
@@ -499,6 +507,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
ACT_SANDBOX_DEPLOY, "/images/icons/deploy.gif",
"#{DialogManager.setupParameters}", "dialog:deployWebsite",
null, dialogParams, false);
+ deploy.setTooltip(Application.getMessage(context, ACT_SANDBOX_DEPLOY) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
menu.getChildren().add(deploy);
}
@@ -509,6 +518,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
ACT_SANDBOX_DEPLOY_REPORT, "/images/icons/deployment_report.gif",
"#{DialogManager.setupParameters}", "dialog:viewDeploymentReport",
null, null, false);
+ reports.setTooltip(Application.getMessage(context, ACT_SANDBOX_DEPLOY_REPORT) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
menu.getChildren().add(reports);
}
@@ -519,6 +529,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
ACT_SANDBOX_RELEASE_SERVER, "/images/icons/release_server.gif",
"#{DialogManager.setupParameters}", "dialog:releaseTestServer",
null, null, false);
+ releaseServer.setTooltip(Application.getMessage(context, ACT_SANDBOX_RELEASE_SERVER) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
menu.getChildren().add(releaseServer);
}
@@ -526,6 +537,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
UIActionLink refresh = createAction(context, mainStore, username,
ACT_SANDBOX_REFRESH, "/images/icons/reset.gif",
"#{AVMBrowseBean.refreshSandbox}", null, null, null, false);
+ refresh.setTooltip(Application.getMessage(context, ACT_SANDBOX_REFRESH) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
menu.getChildren().add(refresh);
// Delete Sandbox action
@@ -535,6 +547,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
ACT_REMOVE_SANDBOX, "/images/icons/delete_sandbox.gif",
"#{AVMBrowseBean.setupSandboxAction}", "dialog:deleteSandbox",
null, null, false);
+ delete.setTooltip(Application.getMessage(context, ACT_REMOVE_SANDBOX) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")");
menu.getChildren().add(delete);
}
@@ -550,9 +563,14 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
{
panelImage = WebResources.IMAGE_EXPANDED;
}
- out.write(Utils.buildImageTag(context, panelImage, 11, 11, "",
- Utils.generateFormSubmit(context, this, getClientId(context) + PANEL_MODIFIED, username + PANEL_MODIFIED)));
- out.write(" ");
+
+ String title = Application.getMessage(context, MSG_MODIFIED_ITEMS) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")";
+ String submitScript = Utils.generateFormSubmit(context, this, getClientId(context) + PANEL_MODIFIED, username + PANEL_MODIFIED);
+ out.write("");
+ out.write(Utils.buildImageTag(context, panelImage, 11, 11, title));
+ out.write("");
+
+ out.write(" ");
out.write(bundle.getString(MSG_MODIFIED_ITEMS));
out.write("");
@@ -576,9 +594,14 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
{
panelImage = WebResources.IMAGE_EXPANDED;
}
- out.write(Utils.buildImageTag(context, panelImage, 11, 11, "",
- Utils.generateFormSubmit(context, this, getClientId(context) + PANEL_FORMS, username + PANEL_FORMS)));
- out.write(" ");
+
+ title = Application.getMessage(context, MSG_CONTENT_FORMS) + " (" + username + " " + Application.getMessage(context, "sandbox_title_extension") + ")";
+ submitScript = Utils.generateFormSubmit(context, this, getClientId(context) + PANEL_FORMS, username + PANEL_FORMS);
+ out.write("");
+ out.write(Utils.buildImageTag(context, panelImage, 11, 11, title));
+ out.write("");
+
+ out.write(" ");
out.write(bundle.getString(MSG_CONTENT_FORMS));
out.write("");
if (this.expandedPanels.contains(username + PANEL_FORMS))
diff --git a/source/test-resources/xforms/unit-tests/all-widgets.xsd b/source/test-resources/xforms/unit-tests/all-widgets.xsd
new file mode 100644
index 0000000000..e41144df02
--- /dev/null
+++ b/source/test-resources/xforms/unit-tests/all-widgets.xsd
@@ -0,0 +1,398 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+ custom
+ full
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file_picker
+ folder_picker
+ html_file_picker
+ image_file_picker
+ search_restricted_file_picker
+ folder_restricted_file_picker
+
+
+
+
+
+
+
+ full
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ full
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/test-resources/xforms/unit-tests/all-widgets_xform.xml b/source/test-resources/xforms/unit-tests/all-widgets_xform.xml
new file mode 100644
index 0000000000..981b6833c9
--- /dev/null
+++ b/source/test-resources/xforms/unit-tests/all-widgets_xform.xml
@@ -0,0 +1,1261 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+
+
+
+
+
+
+ custom
+
+
+
+
+
+
+ full
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file_picker
+
+
+
+
+
+
+ folder_picker
+
+
+
+
+
+
+ html_file_picker
+
+
+
+
+
+
+ image_file_picker
+
+
+
+
+
+
+ search_restricted_file_picker
+
+
+
+
+
+
+ folder_restricted_file_picker
+
+
+
+
+
+
+
+
+
+
+
+
+ full
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ full
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ minimal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AllWidgets
+
+ TextField NormalizedString
+ Please provide a valid value for 'TextField NormalizedString'.
+ 'TextField NormalizedString' is a required 'NormalizedString' value.
+
+
+ PlainTextEditor String Minimal
+ Please provide a valid value for 'PlainTextEditor String Minimal'.
+ 'PlainTextEditor String Minimal' is a required 'String' value.
+
+
+ RichTextEditor String
+ Please provide a valid value for 'RichTextEditor String'.
+ 'RichTextEditor String' is a required 'String' value.
+
+
+ RichTextEditor String Custom
+ Please provide a valid value for 'RichTextEditor String Custom'.
+ 'RichTextEditor String Custom' is a required 'String' value.
+
+
+ RichTextEditor String Full
+ Please provide a valid value for 'RichTextEditor String Full'.
+ 'RichTextEditor String Full' is a required 'String' value.
+
+
+ DatePicker Date
+ Please provide a valid value for 'DatePicker Date'. 'DatePicker Date'
+ is a required 'Date' value.
+
+
+ TimePicker Time
+ Please provide a valid value for 'TimePicker Time'. 'TimePicker Time'
+ is a required 'Time' value.
+
+
+ DateTimePicker DateTime
+ Please provide a valid value for 'DateTimePicker DateTime'.
+ 'DateTimePicker DateTime' is a required 'DateTime' value.
+
+
+ DayPicker GDay
+ Please provide a valid value for 'DayPicker GDay'. 'DayPicker GDay' is
+ a required 'GDay' value.
+
+
+ MonthPicker GMonth
+ Please provide a valid value for 'MonthPicker GMonth'. 'MonthPicker
+ GMonth' is a required 'GMonth' value.
+
+
+ YearPicker GYear
+ Please provide a valid value for 'YearPicker GYear'. 'YearPicker
+ GYear' is a required 'GYear' value.
+
+
+ MonthDayPicker GMonthDay
+ Please provide a valid value for 'MonthDayPicker GMonthDay'.
+ 'MonthDayPicker GMonthDay' is a required 'GMonthDay' value.
+
+
+ YearMonthPicker GYearMonth
+ Please provide a valid value for 'YearMonthPicker GYearMonth'.
+ 'YearMonthPicker GYearMonth' is a required 'GYearMonth' value.
+
+
+
+ true
+ true
+
+
+ false
+ false
+
+ Checkbox Boolean
+ Please provide a valid value for 'Checkbox Boolean'. 'Checkbox
+ Boolean' is a required 'Boolean' value.
+
+
+ NumericalRange Integer
+ Please provide a valid value for 'NumericalRange Integer'.
+ 'NumericalRange Integer' is a required 'Integer' value.
+
+
+
+ FilePicker AnyURI
+ Please provide a valid value for 'FilePicker AnyURI'. 'FilePicker
+ AnyURI' is a required 'AnyURI' value.
+
+
+
+ FilePicker AnyURI File Picker
+ Please provide a valid value for 'FilePicker AnyURI File Picker'.
+ 'FilePicker AnyURI File Picker' is a required 'AnyURI' value.
+
+
+
+ FilePicker AnyURI Folder Picker
+ Please provide a valid value for 'FilePicker AnyURI Folder Picker'.
+ 'FilePicker AnyURI Folder Picker' is a required 'AnyURI' value.
+
+
+
+ FilePicker AnyURI Html File Picker
+ Please provide a valid value for 'FilePicker AnyURI Html File Picker'.
+ 'FilePicker AnyURI Html File Picker' is a required 'AnyURI' value.
+
+
+
+ FilePicker AnyURI Image File Picker
+ Please provide a valid value for 'FilePicker AnyURI Image File
+ Picker'. 'FilePicker AnyURI Image File Picker' is a required 'AnyURI' value.
+
+
+
+ FilePicker AnyURI Search Restricted File Picker
+ Please provide a valid value for 'FilePicker AnyURI Search Restricted
+ File Picker'. 'FilePicker AnyURI Search Restricted File Picker' is a required 'AnyURI'
+ value.
+
+
+
+ FilePicker AnyURI Folder Restricted File Picker
+ Please provide a valid value for 'FilePicker AnyURI Folder Restricted
+ File Picker'. 'FilePicker AnyURI Folder Restricted File Picker' is a required 'AnyURI'
+ value.
+
+
+ CheckboxSelect List Full
+
+
+ Checkbox List Full 1
+ Checkbox List full 1
+
+
+ Checkbox List Full 2
+ Checkbox List full 2
+
+
+ Checkbox List Full 3
+ Checkbox List full 3
+
+
+ Checkbox List Full 4
+ Checkbox List full 4
+
+
+ Checkbox List Full 5
+ Checkbox List full 5
+
+
+ Checkbox List Full 6
+ Checkbox List full 6
+
+
+ Checkbox List Full 7
+ Checkbox List full 7
+
+
+ Checkbox List Full 8
+ Checkbox List full 8
+
+
+ Checkbox List Full 9
+ Checkbox List full 9
+
+
+ Checkbox List Full 10
+ Checkbox List full 10
+
+
+ Please provide a valid value for 'CheckboxSelect List Full'.
+ 'CheckboxSelect List Full' is a required 'NormalizedString' value.
+
+
+ ListSelect List Minimal
+
+
+ List List Minimal 1
+ List List minimal 1
+
+
+ List List Minimal 2
+ List List minimal 2
+
+
+ List List Minimal 3
+ List List minimal 3
+
+
+ List List Minimal 4
+ List List minimal 4
+
+
+ List List Minimal 5
+ List List minimal 5
+
+
+ List List Minimal 6
+ List List minimal 6
+
+
+ List List Minimal 7
+ List List minimal 7
+
+
+ List List Minimal 8
+ List List minimal 8
+
+
+ List List Minimal 9
+ List List minimal 9
+
+
+ List List Minimal 10
+ List List minimal 10
+
+
+ Please provide a valid value for 'ListSelect List Minimal'.
+ 'ListSelect List Minimal' is a required 'NormalizedString' value.
+
+
+ CheckboxSelect List Default Short
+
+
+ Checkbox List Default Short 1
+ Checkbox List default short 1
+
+
+ Checkbox List Default Short 2
+ Checkbox List default short 2
+
+
+ Checkbox List Default Short 3
+ Checkbox List default short 3
+
+
+ Please provide a valid value for 'CheckboxSelect List Default Short'.
+ 'CheckboxSelect List Default Short' is a required 'NormalizedString' value.
+
+
+ ListSelect List Default Long
+
+
+ List List Default Long 1
+ List List default long 1
+
+
+ List List Default Long 2
+ List List default long 2
+
+
+ List List Default Long 3
+ List List default long 3
+
+
+ List List Default Long 4
+ List List default long 4
+
+
+ List List Default Long 5
+ List List default long 5
+
+
+ List List Default Long 6
+ List List default long 6
+
+
+ List List Default Long 7
+ List List default long 7
+
+
+ List List Default Long 8
+ List List default long 8
+
+
+ List List Default Long 9
+ List List default long 9
+
+
+ List List Default Long 10
+ List List default long 10
+
+
+ Please provide a valid value for 'ListSelect List Default Long'.
+ 'ListSelect List Default Long' is a required 'NormalizedString' value.
+
+
+ RadioSelect1 Enum Full
+
+
+ Radio Enum Full 1
+ Radio enum full 1
+
+
+ Radio Enum Full 2
+ Radio enum full 2
+
+
+ Radio Enum Full 3
+ Radio enum full 3
+
+
+ Radio Enum Full 4
+ Radio enum full 4
+
+
+ Radio Enum Full 5
+ Radio enum full 5
+
+
+ Radio Enum Full 6
+ Radio enum full 6
+
+
+ Radio Enum Full 7
+ Radio enum full 7
+
+
+ Radio Enum Full 8
+ Radio enum full 8
+
+
+ Radio Enum Full 9
+ Radio enum full 9
+
+
+ Radio Enum Full 10
+ Radio enum full 10
+
+
+ Please provide a valid value for 'RadioSelect1 Enum Full'.
+ 'RadioSelect1 Enum Full' is a required 'NormalizedString' value.
+
+
+ ComboboxSelect1 Enum Minimal
+
+
+ Please Select...
+ Please select...
+
+
+ Combobox Enum Minimal 1
+ Combobox enum minimal 1
+
+
+ Combobox Enum Minimal 2
+ Combobox enum minimal 2
+
+
+ Combobox Enum Minimal 3
+ Combobox enum minimal 3
+
+
+ Combobox Enum Minimal 4
+ Combobox enum minimal 4
+
+
+ Combobox Enum Minimal 5
+ Combobox enum minimal 5
+
+
+ Combobox Enum Minimal 6
+ Combobox enum minimal 6
+
+
+ Combobox Enum Minimal 7
+ Combobox enum minimal 7
+
+
+ Combobox Enum Minimal 8
+ Combobox enum minimal 8
+
+
+ Combobox Enum Minimal 9
+ Combobox enum minimal 9
+
+
+ Combobox Enum Minimal 10
+ Combobox enum minimal 10
+
+
+ Please provide a valid value for 'ComboboxSelect1 Enum Minimal'.
+ 'ComboboxSelect1 Enum Minimal' is a required 'NormalizedString' value.
+
+
+ RadioSelect1 Enum Default Short
+
+
+ Radio Enum Default Short 1
+ Radio enum default short 1
+
+
+ Radio Enum Default Short 2
+ Radio enum default short 2
+
+
+ Radio Enum Default Short 3
+ Radio enum default short 3
+
+
+ Please provide a valid value for 'RadioSelect1 Enum Default Short'.
+ 'RadioSelect1 Enum Default Short' is a required 'NormalizedString' value.
+
+
+ ComboboxSelect1 Enum Default Long
+
+
+ Please Select...
+ Please select...
+
+
+ Combobox Enum Default Long 1
+ Combobox enum default long 1
+
+
+ Combobox Enum Default Long 2
+ Combobox enum default long 2
+
+
+ Combobox Enum Default Long 3
+ Combobox enum default long 3
+
+
+ Combobox Enum Default Long 4
+ Combobox enum default long 4
+
+
+ Combobox Enum Default Long 5
+ Combobox enum default long 5
+
+
+ Combobox Enum Default Long 6
+ Combobox enum default long 6
+
+
+ Combobox Enum Default Long 7
+ Combobox enum default long 7
+
+
+ Combobox Enum Default Long 8
+ Combobox enum default long 8
+
+
+ Combobox Enum Default Long 9
+ Combobox enum default long 9
+
+
+ Combobox Enum Default Long 10
+ Combobox enum default long 10
+
+
+ Please provide a valid value for 'ComboboxSelect1 Enum Default Long'.
+ 'ComboboxSelect1 Enum Default Long' is a required 'NormalizedString' value.
+
+
+ VGroup ComplexType Sequence
+
+ SequenceString
+ Please provide a valid value for 'SequenceString'. 'SequenceString'
+ is a required 'NormalizedString' value.
+
+
+ SequenceDecimal
+ Please provide a valid value for 'SequenceDecimal'.
+ 'SequenceDecimal' is a required 'Decimal' value.
+
+
+
+ HGroup ComplexType All Minimal
+
+ Horizontal1
+ Please provide a valid value for 'Horizontal1'. 'Horizontal1' is a
+ required 'NormalizedString' value.
+
+
+ Horizontal2
+ Please provide a valid value for 'Horizontal2'. 'Horizontal2' is a
+ required 'NormalizedString' value.
+
+
+
+ Repeat 1to3 NormalizedString
+
+
+
+ Repeat 1to3 NormalizedString
+ Please provide a valid value for 'Repeat 1to3 NormalizedString'.
+ 'Repeat 1to3 NormalizedString' is a required 'NormalizedString' value.
+
+
+
+
+
+ baseComplexType
+
+
+ baseComplexType
+
+
+
+ complexContentType
+
+
+ complexContentType
+
+
+
+ complexContentType2
+
+
+ complexContentType2
+
+
+
+
+ baseComplexType
+
+ Trigger SwitchGroup CaseGroup ComplexType
+
+ Part1
+ Please provide a valid value for 'Part1'. 'Part1' is a required
+ 'NormalizedString' value.
+
+
+ Part2
+ Please provide a valid value for 'Part2'. 'Part2' is a required
+ 'NormalizedString' value.
+
+
+
+
+ complexContentType
+
+ Trigger SwitchGroup CaseGroup ComplexType
+
+ Part1
+ Please provide a valid value for 'Part1'. 'Part1' is a required
+ 'NormalizedString' value.
+
+
+ Part2
+ Please provide a valid value for 'Part2'. 'Part2' is a required
+ 'NormalizedString' value.
+
+
+ Part3
+ Please provide a valid value for 'Part3'. 'Part3' is a required
+ 'NormalizedString' value.
+
+
+ Part4
+ Please provide a valid value for 'Part4'. 'Part4' is a required
+ 'NormalizedString' value.
+
+
+
+
+ complexContentType2
+
+ Trigger SwitchGroup CaseGroup ComplexType
+
+ Part1
+ Please provide a valid value for 'Part1'. 'Part1' is a required
+ 'NormalizedString' value.
+
+
+ Part2
+ Please provide a valid value for 'Part2'. 'Part2' is a required
+ 'NormalizedString' value.
+
+
+ Part5
+ Please provide a valid value for 'Part5'. 'Part5' is a required
+ 'NormalizedString' value.
+
+
+ Part6
+ Please provide a valid value for 'Part6'. 'Part6' is a required
+ 'NormalizedString' value.
+
+
+
+
+
+ Submit
+
+
+ Save Draft
+
+
+ insert at beginning
+
+
+
+
+
+ insert after selected
+
+
+
+
+
+ delete selected
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/web/WEB-INF/faces-config-repo.xml b/source/web/WEB-INF/faces-config-repo.xml
index 275b57c1fd..5ac910e491 100644
--- a/source/web/WEB-INF/faces-config-repo.xml
+++ b/source/web/WEB-INF/faces-config-repo.xml
@@ -68,6 +68,11 @@
org.alfresco.faces.CategorySelector
org.alfresco.web.ui.repo.component.UICategorySelector
+
+
+ org.alfresco.faces.TagSelector
+ org.alfresco.web.ui.repo.component.UITagSelector
+
org.alfresco.faces.MimeTypeSelector
diff --git a/source/web/WEB-INF/web.xml b/source/web/WEB-INF/web.xml
index d78aeede1b..48d4759c37 100644
--- a/source/web/WEB-INF/web.xml
+++ b/source/web/WEB-INF/web.xml
@@ -328,6 +328,11 @@
org.alfresco.web.app.ContextListener
+
+
+ org.alfresco.repo.webdav.WebDAVSessionListener
+
+
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
@@ -335,6 +340,7 @@
+
Faces Servlet
diff --git a/source/web/jsp/rules/compare-date-property.jsp b/source/web/jsp/rules/compare-date-property.jsp
index ee5f8e9943..622158a9ed 100644
--- a/source/web/jsp/rules/compare-date-property.jsp
+++ b/source/web/jsp/rules/compare-date-property.jsp
@@ -196,7 +196,7 @@ function checkButtonState(inputField)
+ disabled="#{empty WizardManager.bean.conditionProperties.qname}" />
|
diff --git a/source/web/jsp/users/email-space-users.jsp b/source/web/jsp/users/email-space-users.jsp
index 9c932fa2e6..1dafe80736 100644
--- a/source/web/jsp/users/email-space-users.jsp
+++ b/source/web/jsp/users/email-space-users.jsp
@@ -30,9 +30,12 @@
function pageLoaded()
{
- document.getElementById("dialog:dialog-body:subject").focus();
- okEnabled = !document.getElementById("dialog:finish-button").disabled;
- checkButtonState();
+ if (document.getElementById("dialog:dialog-body:subject") != null)
+ {
+ document.getElementById("dialog:dialog-body:subject").focus();
+ }
+ okEnabled = !document.getElementById("dialog:finish-button").disabled;
+ checkButtonState();
}
function checkButtonState()
diff --git a/source/web/jsp/wizard/container.jsp b/source/web/jsp/wizard/container.jsp
index 346469d3e5..38549028bf 100644
--- a/source/web/jsp/wizard/container.jsp
+++ b/source/web/jsp/wizard/container.jsp
@@ -1,5 +1,5 @@
<%--
- * Copyright (C) 2005-2010 Alfresco Software Limited.
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -76,15 +76,16 @@ if (Application.getWizardManager().getState() == null)
<%-- Status and Actions inner contents table --%>
<%-- Generally this consists of an icon, textual summary and actions for the current object --%>
-
+ <%-- Accessibility heading level 1 titles --%>
+
@@ -108,11 +109,13 @@ if (Application.getWizardManager().getState() == null)
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "greyround", "#F5F5F5"); %>
-
-
-
-
+
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "greyround"); %>
|
@@ -121,6 +124,17 @@ if (Application.getWizardManager().getState() == null)
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "white", "white"); %>
+
+ <%-- Accessibility heading level 2 titles. FireFox doesn't use labels from the table below --%>
+
+
|
@@ -139,7 +153,11 @@ if (Application.getWizardManager().getState() == null)
|
- |
+
+
+
+
+ |
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %>
@@ -147,6 +165,14 @@ if (Application.getWizardManager().getState() == null)
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "greyround", "#F5F5F5"); %>
+
+ <%-- Accessibility heading level 2 titles --%>
+
+
diff --git a/source/web/scripts/ajax/dojo/src/widget/DatePicker.js b/source/web/scripts/ajax/dojo/src/widget/DatePicker.js
index 9e463ab54d..3fbd497774 100644
--- a/source/web/scripts/ajax/dojo/src/widget/DatePicker.js
+++ b/source/web/scripts/ajax/dojo/src/widget/DatePicker.js
@@ -264,6 +264,11 @@ dojo.widget.defineWidget(
this.selectedNode = currentCalendarNode;
}
nextDate = dojo.date.add(nextDate, dojo.date.dateParts.DAY, 1);
+
+ // DOJO accessibility for Alfresco WCM: ALF-11956
+ var drawableDate = this._getSelectDayMonthAndYear({"target": currentCalendarNode});
+ var month = dojo.date.getNames('months', 'wide', 'standAlone', this.lang)[drawableDate.month];
+ currentCalendarNode.setAttribute("aria-label", (drawableDate.day + " (" + month + ", " + drawableDate.year + ")"));
}
this.lastDay = dojo.date.add(nextDate,dojo.date.dateParts.DAY,-1);
this._initControls();
@@ -395,6 +400,17 @@ dojo.widget.defineWidget(
this._incrementWeek(evt);
}
},
+
+ onIncrementWeekPressed: function(event) {
+ // DOJO accessibility for Alfresco WCM: ALF-11956
+ if(null != event){
+ event.stopPropagation();
+
+ if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){
+ this.onIncrementWeek(event);
+ }
+ }
+ },
onIncrementMonth: function(/*Event*/evt) {
// summary: handler for increment month event
@@ -403,7 +419,18 @@ dojo.widget.defineWidget(
this._incrementMonth(evt);
}
},
-
+
+ onIncrementMonthPressed: function(event) {
+ // DOJO accessibility for Alfresco WCM: ALF-11956
+ if(null != event){
+ event.stopPropagation();
+
+ if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){
+ this.onIncrementMonth(event);
+ }
+ }
+ },
+
onIncrementYear: function(/*Event*/evt) {
// summary: handler for increment year event
evt.stopPropagation();
@@ -411,7 +438,18 @@ dojo.widget.defineWidget(
this._incrementYear(evt);
}
},
-
+
+ onIncrementYearPressed: function(event) {
+ // DOJO accessibility for Alfresco WCM: ALF-11956
+ if(null != event){
+ event.stopPropagation();
+
+ if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){
+ this.onIncrementYear(event);
+ }
+ }
+ },
+
_setMonthLabel: function(monthIndex) {
this.monthLabelNode.innerHTML = dojo.date.getNames('months', 'wide', 'standAlone', this.lang)[monthIndex];
},
@@ -448,14 +486,27 @@ dojo.widget.defineWidget(
},
_handleUiClick: function(/*Event*/evt) {
+ // DOJO accessibility for Alfresco WCM: ALF-11956
+ var selectedDate = this._getSelectDayMonthAndYear(evt);
+ if(null == selectedDate){
+ return;
+ }
+ this.clickedNode = evt.target;
+ this.setDate(new Date(selectedDate.year, selectedDate.month, evt.target.innerHTML));
+ },
+
+ _getSelectDayMonthAndYear: function(evt) {
+ // DOJO accessibility for Alfresco WCM: ALF-11956
var eventTarget = evt.target;
if(eventTarget.nodeType != dojo.dom.ELEMENT_NODE){eventTarget = eventTarget.parentNode;}
- dojo.event.browser.stopEvent(evt);
+ if(null != evt.preventDefault){
+ dojo.event.browser.stopEvent(evt);
+ }
this.selectedIsUsed = this.todayIsUsed = false;
var month = this.curMonth.getMonth();
var year = this.curMonth.getFullYear();
if(dojo.html.hasClass(eventTarget, this.classNames["disabledPrevious"])||dojo.html.hasClass(eventTarget, this.classNames["disabledCurrent"])||dojo.html.hasClass(eventTarget, this.classNames["disabledNext"])){
- return; //this date is disabled... ignore it
+ return null; //this date is disabled... ignore it
}else if (dojo.html.hasClass(eventTarget, this.classNames["next"])) {
month = ++month % 12;
if(month===0){++year;}
@@ -463,10 +514,21 @@ dojo.widget.defineWidget(
month = --month % 12;
if(month==11){--year;}
}
- this.clickedNode = eventTarget;
- this.setDate(new Date(year, month, eventTarget.innerHTML));
+
+ return {"day": eventTarget.innerHTML, "month": month, "year": year};
},
-
+
+ _handleUiPress: function(event) {
+ // DOJO accessibility for Alfresco WCM: ALF-11956
+ if(null != event){
+ event.stopPropagation();
+
+ if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){
+ this._handleUiClick(event);
+ }
+ }
+ },
+
onValueChanged: function(/*Date*/date) {
//summary: the set date event handler
},
diff --git a/source/web/scripts/ajax/dojo/src/widget/TimePicker.js b/source/web/scripts/ajax/dojo/src/widget/TimePicker.js
index 317beaae8f..2aa82a563e 100644
--- a/source/web/scripts/ajax/dojo/src/widget/TimePicker.js
+++ b/source/web/scripts/ajax/dojo/src/widget/TimePicker.js
@@ -275,6 +275,17 @@ dojo.widget.defineWidget(
this.onSetTime();
},
+ onSetSelectedAmPmPressed: function(event) {
+ // DOJO accessibility for Alfresco WCM: ALF-11956
+ if(null != event){
+ event.stopPropagation();
+
+ if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){
+ this.onSetSelectedAmPm(event);
+ }
+ }
+ },
+
setSelectedAmPm: function(evt) {
var eventTarget = evt.target;
if(evt && eventTarget) {
diff --git a/source/web/scripts/ajax/dojo/src/widget/templates/DatePicker.html b/source/web/scripts/ajax/dojo/src/widget/templates/DatePicker.html
index b97a0d1d21..db7619eab5 100644
--- a/source/web/scripts/ajax/dojo/src/widget/templates/DatePicker.html
+++ b/source/web/scripts/ajax/dojo/src/widget/templates/DatePicker.html
@@ -7,31 +7,31 @@
|
|
-
-
+ dojoAttachEvent="onClick: onIncrementMonth; onKey: onIncrementMonthPressed;" class="incrementControl increase">
-
-
+ dojoAttachEvent="onClick: onIncrementMonth; onKey: onIncrementMonthPressed;" class="incrementControl decrease">
-
+
|
|
@@ -55,15 +55,15 @@
+ dojoAttachEvent="onClick: _handleUiClick; onKey: _handleUiPress;">
- |
- |
- |
- |
- |
- |
- |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
@@ -77,13 +77,13 @@
|
|
-
-
-
-
-
+
+
+
+
+
|
|
diff --git a/source/web/scripts/ajax/dojo/src/widget/templates/TimePicker.html b/source/web/scripts/ajax/dojo/src/widget/templates/TimePicker.html
index 0b1e5a52ec..91b1e26b46 100644
--- a/source/web/scripts/ajax/dojo/src/widget/templates/TimePicker.html
+++ b/source/web/scripts/ajax/dojo/src/widget/templates/TimePicker.html
@@ -15,28 +15,28 @@
- 12 |
- 6 |
+ 12 |
+ 6 |
- 1 |
- 7 |
+ 1 |
+ 7 |
- 2 |
- 8 |
+ 2 |
+ 8 |
- 3 |
- 9 |
+ 3 |
+ 9 |
- 4 |
- 10 |
+ 4 |
+ 10 |
- 5 |
- 11 |
+ 5 |
+ 11 |
@@ -46,28 +46,28 @@
- 00 |
- 30 |
+ 00 |
+ 30 |
- 05 |
- 35 |
+ 05 |
+ 35 |
- 10 |
- 40 |
+ 10 |
+ 40 |
- 15 |
- 45 |
+ 15 |
+ 45 |
- 20 |
- 50 |
+ 20 |
+ 50 |
- 25 |
- 55 |
+ 25 |
+ 55 |
@@ -78,10 +78,10 @@
+ dojoAttachEvent="onClick: onSetSelectedAmPm; onKey: onSetSelectedAmPmPressed;">
- ${this.calendar.am} |
- ${this.calendar.pm} |
+ ${this.calendar.am} |
+ ${this.calendar.pm} |
diff --git a/source/web/scripts/ajax/file_picker_widget.js b/source/web/scripts/ajax/file_picker_widget.js
index 9235ba026b..183385be44 100644
--- a/source/web/scripts/ajax/file_picker_widget.js
+++ b/source/web/scripts/ajax/file_picker_widget.js
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2010 Alfresco Software Limited.
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -193,6 +193,7 @@ _showSelectedValue: function()
this.resize_callback(this);
this.selectedPathInput = d.createElement("input");
+ this.selectedPathInput.id = this.uploadId + "-selected-path";
this.selectedPathInput.type = "text";
this.selectedPathInput.value = this.value == null ? "" : this.value;
this.node.appendChild(this.selectedPathInput);
@@ -206,6 +207,7 @@ _showSelectedValue: function()
this._selectButton.value = (this.value == null
? alfresco.resources["select"]
: alfresco.resources["change"]);
+ this._selectButton.title = (null == this.node.widget.labelNode) ? ("") : (this.node.widget.labelNode.getText() + " ") + this._selectButton.value + " " + alfresco.resources["path"];
this._selectButton.disabled = this.readonly;
this._selectButton.style.margin = "0px 10px";
this.node.appendChild(this._selectButton);
@@ -332,6 +334,8 @@ _showPicker: function(data)
this.headerMenuTriggerLink.appendChild(headerMenuTriggerImage);
this.headerMenuTriggerLink.image = headerMenuTriggerImage;
headerMenuTriggerImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/menu.gif");
+ headerMenuTriggerImage.setAttribute("alt", alfresco.resources["select_path_menu"]);
+ headerMenuTriggerImage.setAttribute("title", alfresco.resources["select_path_menu"]);
headerMenuTriggerImage.style.borderWidth = "0px";
headerMenuTriggerImage.style.marginLeft = "4px";
headerMenuTriggerImage.align = "absmiddle";
@@ -364,6 +368,8 @@ _showPicker: function(data)
addContentImage.style.margin = "0px 2px 0px 2px";
addContentImage.align = "absmiddle";
addContentImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/add.gif");
+ addContentImage.setAttribute("alt", "");
+ addContentImage.setAttribute("title", "");
addContentLink.appendChild(addContentImage);
addContentLink.appendChild(d.createTextNode(alfresco.resources["add_content"]));
@@ -395,6 +401,8 @@ _showPicker: function(data)
navigateToParentNodeImage.style.margin = "0px 2px 0px 2px";
navigateToParentNodeImage.align = "absmiddle";
navigateToParentNodeImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/up.gif");
+ navigateToParentNodeImage.setAttribute("alt", "");
+ navigateToParentNodeImage.setAttribute("title", "");
navigateToParentLink.appendChild(navigateToParentNodeImage);
navigateToParentLink.appendChild(d.createTextNode(alfresco.resources["go_up"]));
@@ -419,6 +427,7 @@ _showPicker: function(data)
cancelButton.filePickerWidget = this;
cancelButton.value = alfresco.resources["cancel"];
+ cancelButton.title = (null == this.node.widget.labelNode) ? ("") : (this.node.widget.labelNode.getText() + " ") + alfresco.resources["cancel"];
footerDiv.appendChild(cancelButton);
cancelButton.style.margin = ((.5 * footerDiv.offsetHeight) -
@@ -506,6 +515,7 @@ _createRow: function(fileName, webappRelativePath, isDirectory, isSelectable, f
e.type = "button";
e.name = webappRelativePath;
e.value = "Select";
+ e.title = ((null != this.node.widget.labelNode) ? (this.node.widget.labelNode.getText()) : ("")) + " " + e.value + " " + webappRelativePath;
result.appendChild(e);
e.style.position = "absolute";
@@ -797,6 +807,7 @@ _showSelectedValue: function()
this.resize_callback(this);
this.selectedPathInput = new Element("input",
{
+ "id": this.node.id + "-selected-path",
"type":"text",
"value": (this.value == null ? "" : this.value),
"styles": {"margin":"0"},
@@ -823,6 +834,7 @@ _showSelectedValue: function()
: alfresco.resources["change"]),
"disabled":this.readonly,
"styles":{"margin":"0 3px"},
+ "title": (node.widget.labelNode == null ? "" : node.widget.labelNode.getText()),
"events":
{
"click": function(event)
@@ -836,6 +848,7 @@ _showSelectedValue: function()
}
});
this._selectButton.filePickerWidget = this;
+ this._selectButton.title = (null == this.node.widget.labelNode) ? ("") : (this.node.widget.labelNode.getText() + " ") + this._selectButton.value + " " + alfresco.resources["path"],
this._selectButton.inject(this.wrapper);
var nodeSize = node.getSize();
var selectButtonSize = this._selectButton.getSize();
@@ -944,7 +957,9 @@ _showPicker: function(data)
var headerMenuTriggerImage = new Element("img",
{
"src": alfresco.constants.WEBAPP_CONTEXT + "/images/icons/menu.gif",
- "styles" : {"border":"0", "width:":"16px", "height":"16px", "margin":"0 0 0 4px", "z-index":"500", "vertical-align":"middle"}
+ "styles" : {"border":"0", "width:":"16px", "height":"16px", "margin":"0 0 0 4px", "z-index":"500", "vertical-align":"middle"},
+ "alt": alfresco.resources["select_path_menu"],
+ "title": alfresco.resources["select_path_menu"]
});
headerMenuTriggerImage.inject(this.headerMenuTriggerLink);
@@ -974,7 +989,9 @@ _showPicker: function(data)
var addContentImage = new Element("img",
{
"src":alfresco.constants.WEBAPP_CONTEXT + "/images/icons/add.gif",
- "styles":{"border":"0", "width:":"16px", "height":"16px", "margin":"0 2px", "vertical-align":"middle"}
+ "styles":{"border":"0", "width:":"16px", "height":"16px", "margin":"0 2px", "vertical-align":"middle"},
+ "alt": "",
+ "title": ""
});
addContentImage.inject(addContentLink);
@@ -1004,7 +1021,9 @@ _showPicker: function(data)
var navigateToParentNodeImage = new Element("img",
{
"src":alfresco.constants.WEBAPP_CONTEXT + "/images/icons/up.gif",
- "styles":{"border":"0", "width:":"16px", "height":"16px", "margin":"0 2px", "vertical-align":"middle"}
+ "styles":{"border":"0", "width:":"16px", "height":"16px", "margin":"0 2px", "vertical-align":"middle"},
+ "alt": "",
+ "title": ""
});
dojo.html.setOpacity(navigateToParentNodeImage, (currentPathName == "/" ? .3 : 1));
navigateToParentNodeImage.inject(navigateToParentLink);
@@ -1016,6 +1035,7 @@ _showPicker: function(data)
{
"type" : "button",
"value" : alfresco.resources["cancel"],
+ "title": ((null == this.node.widget.labelNode) ? ("") : (this.node.widget.labelNode.getText() + " ") + alfresco.resources["cancel"]),
"events" : {
"click" : function(event)
{
@@ -1148,6 +1168,7 @@ _createRow: function(fileName, webappRelativePath, isDirectory, isSelectable, f
}
}
);
+ e.title = ((null != this.node.widget.labelNode) ? (this.node.widget.labelNode.getText()) : ("")) + " " + e.value + " " + webappRelativePath;
e.inject(result);
}
return result;
diff --git a/source/web/scripts/ajax/xforms.js b/source/web/scripts/ajax/xforms.js
index 17335fb077..7117b166c1 100644
--- a/source/web/scripts/ajax/xforms.js
+++ b/source/web/scripts/ajax/xforms.js
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2010 Alfresco Software Limited.
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -923,6 +923,25 @@ alfresco.xforms.RichTextEditor = alfresco.xforms.Widget.extend({
alfresco.xforms.RichTextEditor.clickMask.setText(alfresco.resources["click_to_edit"]);
alfresco.xforms.RichTextEditor.clickMask.id = 'xformsRichTextEditorHoverLayer';
alfresco.xforms.RichTextEditor.clickMask.style.display='none';
+
+ alfresco.xforms.RichTextEditor.maskFocusHandler = new Element("a");
+ alfresco.xforms.RichTextEditor.maskFocusHandler.src = "#";
+ alfresco.xforms.RichTextEditor.maskFocusHandler.accessKey = "e";
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.width = "1px";
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.height = "1px";
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.position = "absolute";
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.border.width = 0;
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.padding = 0;
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.margin = 0;
+ alfresco.xforms.RichTextEditor.maskFocusHandler.tabIndex = 0;
+ alfresco.xforms.RichTextEditor.maskFocusHandler.innerHTML = '' + this.getLabel() + ' ';
+
+ alfresco.xforms.RichTextEditor.maskFocusHandler.onfocus = function()
+ {
+ alfresco.xforms.RichTextEditor.clickMask.onclick();
+ return;
+ };
+
document.body.appendChild(alfresco.xforms.RichTextEditor.clickMask);
}
},
@@ -995,6 +1014,10 @@ alfresco.xforms.RichTextEditor = alfresco.xforms.Widget.extend({
render: function(attach_point)
{
+ attach_point.appendChild(alfresco.xforms.RichTextEditor.maskFocusHandler);
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.top = this.domNode.style.top;
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.left = this.domNode.style.left;
+
attach_point.appendChild(this.domNode);
this.domNode.addClass("xformsTextArea");
if (this._params.height)
@@ -1232,6 +1255,10 @@ alfresco.xforms.RichTextEditor = alfresco.xforms.Widget.extend({
_hoverLayer_clickHandler: function(event)
{
alfresco.xforms.RichTextEditor.clickMask.style.display='none'
+
+ alfresco.xforms.RichTextEditor.maskFocusHandler.tabIndex = -1;
+ alfresco.xforms.RichTextEditor.maskFocusHandler.style.display = "none";
+
document.body.appendChild(alfresco.xforms.RichTextEditor.clickMask);
if (alfresco.xforms.RichTextEditor.currentInstance && document.getElementById(alfresco.xforms.RichTextEditor.currentInstance.domNode.id)
&& alfresco.xforms.RichTextEditor.currentInstance != this)
@@ -1393,6 +1420,7 @@ alfresco.xforms.CheckboxSelect = alfresco.xforms.AbstractSelectWidget.extend({
checkbox.setAttribute("id", this.id + "_" + i + "-widget");
checkbox.setAttribute("name", this.id + "_" + i + "-widget");
checkbox.setAttribute("type", "checkbox");
+ checkbox.setAttribute("title", values[i].label);
checkbox.setAttribute("value", values[i].value);
checkboxDiv.appendChild(checkbox);
if (initial_value.indexOf(values[i].value) != -1)
@@ -1400,7 +1428,12 @@ alfresco.xforms.CheckboxSelect = alfresco.xforms.AbstractSelectWidget.extend({
this._selectedValues.push(values[i].value);
checkbox.checked = true;
}
- checkboxDiv.appendChild(document.createTextNode(values[i].label));
+
+ var label = new Element("label", {"for": checkbox.id});
+ label.title = values[i].label;
+ label.appendChild(document.createTextNode(values[i].label));
+
+ checkboxDiv.appendChild(label);
checkbox.onclick = this._checkbox_clickHandler.bindAsEventListener(this);
}
},
@@ -1455,7 +1488,10 @@ alfresco.xforms.CheckboxSelect = alfresco.xforms.AbstractSelectWidget.extend({
alfresco.xforms.ListSelect = alfresco.xforms.AbstractSelectWidget.extend({
initialize: function(xform, xformsNode, parentWidget)
{
- this.parent(xform, xformsNode, parentWidget, new Element("select"));
+ var select = new Element("select");
+ var idPrefix = (null != parentWidget) ? (parentWidget.id) : (xformsNode.id);
+ select.setAttribute("id", idPrefix + "-select");
+ this.parent(xform, xformsNode, parentWidget, select);
},
/////////////////////////////////////////////////////////////////
@@ -1572,11 +1608,17 @@ alfresco.xforms.RadioSelect1 = alfresco.xforms.AbstractSelectWidget.extend({
radio_div.style.lineHeight = "16px";
this.widget.appendChild(radio_div);
var radio = new Element("input");
- radio.setAttribute("id", this.id + "-widget");
+ radio.setAttribute("id", this.id + "-" + i + "-widget");
radio.setAttribute("name", this.id + "-widget");
radio.setAttribute("type", "radio");
+ radio.setAttribute("title", values[i].label);
radio_div.appendChild(radio);
- radio_div.appendChild(document.createTextNode(values[i].label));
+
+ var label = new Element("label", {"for": radio.id});
+ label.title = values[i].label;
+ label.appendChild(document.createTextNode(values[i].label));
+
+ radio_div.appendChild(label);
radio.setAttribute("value", values[i].value);
if (values[i].value == initial_value)
@@ -1658,7 +1700,10 @@ alfresco.xforms.RadioSelect1 = alfresco.xforms.AbstractSelectWidget.extend({
alfresco.xforms.ComboboxSelect1 = alfresco.xforms.AbstractSelectWidget.extend({
initialize: function(xform, xformsNode, parentWidget)
{
- this.parent(xform, xformsNode, parentWidget, new Element("select"));
+ var select = new Element("select");
+ var idPrefix = (null != parentWidget) ? (parentWidget.id) : (xformsNode.id);
+ select.setAttribute("id", idPrefix + "-select");
+ this.parent(xform, xformsNode, parentWidget, select);
},
/////////////////////////////////////////////////////////////////
@@ -1670,6 +1715,7 @@ alfresco.xforms.ComboboxSelect1 = alfresco.xforms.AbstractSelectWidget.extend({
var values = this._getItemValues();
var initial_value = this.getInitialValue();
this.domNode = new Element("select");
+ this.domNode.id = attach_point.id + "-select2";
attach_point.appendChild(this.domNode);
this.widget = this.domNode;
for (var i = 0; i < values.length; i++)
@@ -1811,6 +1857,8 @@ alfresco.xforms.Checkbox = alfresco.xforms.Widget.extend({
alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
initialize: function(xform, xformsNode, parentWidget)
{
+ _createExternalLabels(_getDateTimePickerLabels(parentWidget.domNode));
+
this.parent(xform, xformsNode, parentWidget);
this._minInclusive = (_hasAttribute(this.xformsNode, alfresco.xforms.constants.ALFRESCO_PREFIX + ":minInclusive")
? this.xformsNode.getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":minInclusive")
@@ -1858,12 +1906,24 @@ alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
"onValueChanged",
this,
this._datePicker_valueChangedHandler);
+
+ var expandoImage = document.getElementById(this.domNode.id + "-expanded-image");
+ if (null != expandoImage)
+ {
+ expandoImage.alt = this._buildExpandoImageTitle(true);
+ }
},
_destroyPicker: function()
{
if (this.widget.picker)
{
+ var expandoImage = document.getElementById(this.domNode.id + "-expanded-image");
+ if (null != expandoImage)
+ {
+ expandoImage.alt = this._buildExpandoImageTitle(false);
+ }
+
this.domNode.parentNode.removeChild(this.widget.picker.domNode);
this.widget.picker = null;
this.domContainer.style.height =
@@ -1882,7 +1942,11 @@ alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
{
var initial_value = this.getInitialValue();
attach_point.appendChild(this.domNode);
- this.widget = new Element("input", { "id": this.id + "-widget", "type": "text"});
+ this.widget = new Element("input", { "id": this.id + "-widget", "type": "text", "aria-live": "polite"});
+
+ this.widget.setAttribute("alt", alfresco.resources["date_picker_title"]);
+ this.widget.setAttribute("title", alfresco.resources["date_picker_title"]);
+
if (initial_value)
{
var jsDate = dojo.date.fromRfc3339(initial_value);
@@ -1903,20 +1967,41 @@ alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
this.domNode.appendChild(this.widget);
var expandoImage = new Element("img");
+ expandoImage.id = this.domNode.id + "-expanded-image";
expandoImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/action.gif");
expandoImage.align = "absmiddle";
expandoImage.style.margin = "0px 5px";
+ expandoImage.tabIndex = 0;
+
+ var imageTitle = this._buildExpandoImageTitle(false);
+
+ expandoImage.setAttribute("alt", imageTitle);
+ expandoImage.setAttribute("title", alfresco.resources["date_picker_title"]);
this.domNode.appendChild(expandoImage);
if (!this.isReadonly())
{
expandoImage.onclick = this._expando_clickHandler.bindAsEventListener(this);
+ expandoImage.onkeypress = this._expando_keypressHandler.bindAsEventListener(this);
+
this.widget.onfocus = this._dateTextBox_focusHandler.bindAsEventListener(this);
this.widget.onchange = this._dateTextBox_changeHandler.bindAsEventListener(this);
}
},
+ _buildExpandoImageTitle: function(expanded)
+ {
+ var result = "";
+ if ((null != this.labelNode) && (null != this.labelNode.getText()) && (this.labelNode.getText().length > 0))
+ {
+ result = this.labelNode.getText() + " ";
+ }
+ result += alfresco.resources["date_picker_button_title"] + ". " + ((expanded) ? (alfresco.resources["state_expanded"]) : (alfresco.resources["state_not_expanded"])) + ".";
+
+ return result;
+ },
+
setValue: function(value, forceCommit)
{
if (!this.widget)
@@ -1969,6 +2054,11 @@ alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
{
var rfcDate = dojo.date.toRfc3339(date, "dateOnly");
this._destroyPicker();
+
+ var imageTitle = this._buildExpandoImageTitle(false);
+ var expandoImage = document.getElementById(this.domNode.id + "-expanded-image");
+ expandoImage.alt = imageTitle;
+
this.setValue(rfcDate);
this._commitValueChange();
},
@@ -1983,6 +2073,14 @@ alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
{
this._createPicker();
}
+ },
+
+ _expando_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._expando_clickHandler();
+ }
}
});
@@ -1990,6 +2088,8 @@ alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
alfresco.xforms.TimePicker = alfresco.xforms.Widget.extend({
initialize: function(xform, xformsNode, parentWidget)
{
+ _createExternalLabels(_getDateTimePickerLabels(parentWidget.domNode));
+
this.parent(xform, xformsNode, parentWidget);
dojo.require("dojo.date.format");
this._noValueSet = (alfresco.resources["eg"] + " " +
@@ -2042,12 +2142,24 @@ alfresco.xforms.TimePicker = alfresco.xforms.Widget.extend({
"onValueChanged",
this,
this._timePicker_valueChangedHandler);
+
+ var expandoImage = document.getElementById(this.domNode.id + "-expanded-image");
+ if (null != expandoImage)
+ {
+ expandoImage.alt = this._buildExpandoImageTitle(true);
+ }
},
_destroyPicker: function()
{
if (this.widget.picker)
{
+ var expandoImage = document.getElementById(this.domNode.id + "-expanded-image");
+ if (null != expandoImage)
+ {
+ expandoImage.alt = this._buildExpandoImageTitle(false);
+ }
+
this.domNode.removeChild(this.widget.picker.domNode);
this.widget.picker = null;
this.domContainer.style.height =
@@ -2067,7 +2179,11 @@ alfresco.xforms.TimePicker = alfresco.xforms.Widget.extend({
var initial_value = this.getInitialValue();
attach_point.appendChild(this.domNode);
- this.widget = new Element("input", { "id": this.id + "-widget", "type": "text" });
+ this.widget = new Element("input", { "id": this.id + "-widget", "type": "text", "aria-live": "polite" });
+
+ this.widget.setAttribute("alt", alfresco.resources["time_picker_title"]);
+ this.widget.setAttribute("title", alfresco.resources["time_picker_title"]);
+
if (initial_value)
{
var jsDate = this._parseTime(initial_value);
@@ -2088,20 +2204,41 @@ alfresco.xforms.TimePicker = alfresco.xforms.Widget.extend({
this.domNode.appendChild(this.widget);
var expandoImage = new Element("img");
+ expandoImage.id = this.domNode.id + "-expanded-image";
expandoImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/action.gif");
expandoImage.align = "absmiddle";
expandoImage.style.margin = "0px 5px";
+ expandoImage.tabIndex = 0;
+
+ var imageTitle = this._buildExpandoImageTitle(false);
+
+ expandoImage.setAttribute("alt", imageTitle);
+ expandoImage.setAttribute("title", alfresco.resources["time_picker_title"]);
this.domNode.appendChild(expandoImage);
if (!this.isReadonly())
{
expandoImage.onclick = this._expando_clickHandler.bindAsEventListener(this);
+ expandoImage.onkeypress = this._expando_keypressHandler.bindAsEventListener(this);
+
this.widget.onfocus = this._timeTextBox_focusHandler.bindAsEventListener(this);
this.widget.onchange = this._timeTextBox_changeHandler.bindAsEventListener(this);
}
},
+ _buildExpandoImageTitle: function(expanded)
+ {
+ var result = "";
+ if ((null != this.labelNode) && (null != this.labelNode.getText()) && (this.labelNode.getText().length > 0))
+ {
+ result = this.labelNode.getText() + " ";
+ }
+ result += alfresco.resources["time_picker_button_title"] + ". " + ((expanded) ? (alfresco.resources["state_expanded"]) : (alfresco.resources["state_not_expanded"])) + ".";
+
+ return result;
+ },
+
setValue: function(value, forceCommit)
{
if (!this.widget)
@@ -2167,6 +2304,14 @@ alfresco.xforms.TimePicker = alfresco.xforms.Widget.extend({
{
this._createPicker();
}
+ },
+
+ _expando_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._expando_clickHandler();
+ }
}
});
@@ -2174,6 +2319,8 @@ alfresco.xforms.TimePicker = alfresco.xforms.Widget.extend({
alfresco.xforms.DateTimePicker = alfresco.xforms.Widget.extend({
initialize: function(xform, xformsNode, parentWidget)
{
+ _createExternalLabels(_getDateTimePickerLabels(parentWidget.domNode));
+
this.parent(xform, xformsNode, parentWidget);
dojo.require("dojo.date.format");
this._noValueSet = (alfresco.resources["eg"] + " " +
@@ -2237,12 +2384,24 @@ alfresco.xforms.DateTimePicker = alfresco.xforms.Widget.extend({
"onValueChanged",
this,
this._timePicker_valueChangedHandler);
+
+ var expandoImage = document.getElementById(this.domNode.id + "-expanded-image");
+ if (null != expandoImage)
+ {
+ expandoImage.alt = this._buildExpandoImageTitle(true);
+ }
},
_destroyPicker: function()
{
if (this._pickerDiv)
{
+ var expandoImage = document.getElementById(this.domNode.id + "-expanded-image");
+ if (null != expandoImage)
+ {
+ expandoImage.alt = this._buildExpandoImageTitle(false);
+ }
+
this.domNode.removeChild(this._pickerDiv);
this.widget.datePicker = null;
this.widget.timePicker = null;
@@ -2264,7 +2423,11 @@ alfresco.xforms.DateTimePicker = alfresco.xforms.Widget.extend({
var initial_value = this.getInitialValue();
attach_point.appendChild(this.domNode);
- this.widget = new Element("input", { "id": this.id + "-widget", "type": "text" });
+ this.widget = new Element("input", { "id": this.id + "-widget", "type": "text", "aria-live": "polite" });
+
+ this.widget.setAttribute("alt", alfresco.resources["date_time_picker_title"]);
+ this.widget.setAttribute("title", alfresco.resources["date_time_picker_title"]);
+
if (initial_value)
{
var jsDate = dojo.date.fromRfc3339(initial_value);
@@ -2282,17 +2445,38 @@ alfresco.xforms.DateTimePicker = alfresco.xforms.Widget.extend({
this.widget.style.width = (3 * this.widget.offsetWidth) + "px";
var expandoImage = new Element("img");
+ expandoImage.id = this.domNode.id + "-expanded-image";
expandoImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/action.gif");
expandoImage.align = "absmiddle";
expandoImage.style.margin = "0px 5px";
+ expandoImage.tabIndex = 0;
+
+ var imageTitle = this._buildExpandoImageTitle(false);
+
+ expandoImage.setAttribute("alt", imageTitle);
+ expandoImage.setAttribute("title", alfresco.resources["date_time_picker_title"]);
this.domNode.appendChild(expandoImage);
expandoImage.onclick = this._expando_clickHandler.bindAsEventListener(this);
+ expandoImage.onkeypress = this._expando_keypressHandler.bindAsEventListener(this);
+
this.widget.onfocus = this._dateTimeTextBox_focusHandler.bindAsEventListener(this);
this.widget.onchange = this._dateTimeTextBox_changeHandler.bindAsEventListener(this);
},
+ _buildExpandoImageTitle: function(expanded)
+ {
+ var result = "";
+ if ((null != this.labelNode) && (null != this.labelNode.getText()) && (this.labelNode.getText().length > 0))
+ {
+ result = this.labelNode.getText() + " ";
+ }
+ result += alfresco.resources["date_time_picker_button_title"] + ". " + ((expanded) ? (alfresco.resources["state_expanded"]) : (alfresco.resources["state_not_expanded"])) + ".";
+
+ return result;
+ },
+
setValue: function(value, forceCommit)
{
if (!this.widget)
@@ -2372,6 +2556,14 @@ alfresco.xforms.DateTimePicker = alfresco.xforms.Widget.extend({
{
this._createPicker();
}
+ },
+
+ _expando_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._expando_clickHandler();
+ }
}
});
@@ -2677,6 +2869,20 @@ alfresco.xforms.AbstractGroup = alfresco.xforms.Widget.extend({
id: child.id + "-label",
"class": "xformsItemLabelContainer"
});
+
+ var result = labelNode;
+
+ var needsInLabel = (null != child.domNode) && (null != child.domNode.id) && !document.getElementById(child.domNode.id);
+
+ if (needsInLabel)
+ {
+ var labelLabel = new Element("label", {"id": (child.id + "-accessibility-label")});
+
+ labelNode.appendChild(labelLabel);
+
+ labelNode = labelLabel;
+ }
+
var requiredImage = new Element("img", { "class": "xformsItemRequiredImage" });
requiredImage.src = alfresco.xforms.AbstractGroup._requiredImage.src;
@@ -2689,21 +2895,57 @@ alfresco.xforms.AbstractGroup = alfresco.xforms.Widget.extend({
var label = child.getLabel();
if (label)
{
- child.labelNode = labelNode;
- child.labelNode.appendChild(document.createTextNode(label));
+ child.labelNode = result;
+
+ if (needsInLabel)
+ {
+ labelLabel.appendChild(document.createTextNode(label));
+ }
+ else
+ {
+ child.labelNode.appendChild(document.createTextNode(label));
+ }
}
var hint = child.getHint();
if (hint)
{
- labelNode.setAttribute("title", hint);
- requiredImage.setAttribute("alt", hint);
+ result.setAttribute("title", hint);
+ requiredImage.setAttribute("alt", (alfresco.resources["mandatory_parameter"] + " " + hint));
}
- labelNode.style.width = "0px";
- $pick(attach_point, child.domContainer).appendChild(labelNode);
- labelNode.style.width = labelNode.scrollWidth + "px";
- return labelNode;
+ else
+ {
+ requiredImage.setAttribute("alt", alfresco.resources["mandatory_parameter"]);
+ }
+ result.style.width = "0px";
+ $pick(attach_point, child.domContainer).appendChild(result);
+ result.style.width = result.scrollWidth + "px";
+
+ return result;
},
+ _findControlElement: function(element)
+ {
+ if ((("A" == element.tagName) || ("INPUT" == element.tagName) || ("SELECT" == element.tagName)) && ("hidden" != element.visibility) && ("none" != element.style.display) && (element.tabIndex >= 0))
+ {
+ return element;
+ }
+
+ if(null != element.children)
+ {
+ for (var i = 0; i < element.children.length; i++)
+ {
+ var result = this._findControlElement(element.children[i]);
+
+ if(null != result)
+ {
+ return result;
+ }
+ }
+ }
+
+ return null;
+ },
+
/////////////////////////////////////////////////////////////////
// overridden methods & properties
/////////////////////////////////////////////////////////////////
@@ -2876,7 +3118,14 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
}
contentDiv.style.width = contentDivWidth;
child.render(contentDiv);
-
+
+ var labelLabel = document.getElementById(child.id + "-accessibility-label");
+ if (null != labelLabel)
+ {
+ var labelOwner = this._findControlElement(child.domNode);
+ labelLabel.setAttribute("for", ((null != labelOwner) ? (labelOwner) : (child.domNode)).id);
+ }
+
var oh = contentDiv.offsetHeight;
var mt = contentDiv.getStyle("margin-top").toInt();
if (!(child instanceof alfresco.xforms.AbstractGroup))
@@ -2947,15 +3196,23 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
});
this.domNode.appendChild(this._groupHeaderNode);
+ var imageTitle = this._buildAccessibilityLabel(this.getLabel(), true);
+
this.toggleExpandedImage = new Element("img",
{
+ "id": (this.id + "-exapndoImage"),
"align": "absmiddle",
"styles": { "margin": "0px 5px" },
- "src": alfresco.xforms.constants.EXPANDED_IMAGE.src
+ "src": alfresco.xforms.constants.EXPANDED_IMAGE.src,
+ "tabIndex": 0,
+ "alt": imageTitle,
+ "title": this.getLabel()
});
- this._groupHeaderNode.appendChild(this.toggleExpandedImage);
+ this._configureHeadingElements(this._groupHeaderNode, this.toggleExpandedImage);
+
this.toggleExpandedImage.onclick = this._toggleExpanded_clickHandler.bindAsEventListener(this);
-
+ this.toggleExpandedImage.onkeypress = this._toggleExpanded_keypressHandler.bindAsEventListener(this);
+
this._groupHeaderNode.appendChild(document.createTextNode(this.getLabel()));
}
attach_point.appendChild(this.domNode);
@@ -2967,6 +3224,34 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
return this.domNode;
},
+ _buildAccessibilityLabel: function(label, expanded)
+ {
+ var result = "";
+ if ((null != label) && (0 != label.length))
+ {
+ result = label + ". ";
+ }
+ result += ((expanded) ? (alfresco.resources["state_expanded"]) : (alfresco.resources["state_not_expanded"])) + ".";
+
+ return result;
+ },
+
+ _configureHeadingElements: function(parentWidget, child)
+ {
+ if (null != parentWidget)
+ {
+ var heading = new Element("span",
+ {
+ "id": (this.id + "-headingElement"),
+ "role": "heading",
+ "aria-level": "3",
+ "aria-labelledby": (this.id + "-exapndoImage")
+ });
+ heading.appendChild(child);
+ parentWidget.appendChild(heading);
+ }
+ },
+
/** Indicates if the group is expanded. */
isExpanded: function()
{
@@ -2987,6 +3272,9 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
? alfresco.xforms.constants.EXPANDED_IMAGE.src
: alfresco.xforms.constants.COLLAPSED_IMAGE.src);
this.domNode.childContainerNode.style.display = expanded ? "block" : "none";
+
+ this.toggleExpandedImage.alt = this._buildAccessibilityLabel(this.getLabel(), this.isExpanded());
+ this.toggleExpandedImage.title = this.toggleExpandedImage.alt;
}
},
@@ -3074,6 +3362,14 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
_toggleExpanded_clickHandler: function(event)
{
this.setExpanded(!this.isExpanded());
+ },
+
+ _toggleExpanded_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this.setExpanded(!this.isExpanded());
+ }
}
});
@@ -3127,7 +3423,18 @@ alfresco.xforms.HGroup = alfresco.xforms.AbstractGroup.extend({
contentDiv.labelNode = labelNode;
child.render(contentDiv);
-
+
+ var labelLabel = document.getElementById(child.id + "-accessibility-label");
+ if (null != labelLabel)
+ {
+ var labelOwner = this._findControlElement(child.domNode);
+ labelLabel.setAttribute("for", ((null != labelOwner) ? (labelOwner) : (child.domNode)).id);
+ }
+
+ var labelOwner = this._findControlElement(child.domNode);
+ var labelLabel = document.getElementById(child.id + "-accessibility-label");
+ labelLabel.setAttribute("for", ((null != labelOwner) ? (labelOwner) : (child.domNode)).id);
+
var w = child.domNode.style.width;
if (!w || w[w.length - 1] != "%")
{
@@ -3587,12 +3894,29 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
{
var insertEnabled = this.isInsertRepeatItemEnabled();
var removeEnabled = this.isRemoveRepeatItemEnabled();
+
+ var label = this.getLabel();
+ label = (null != label) ? (label + " ") : ("");
+
for (var i = 0; i < this._repeatControls.length; i++)
{
+ var labelPrefix = label + alfresco.resources["item_title"] + " " + (i + 1) + ". "
+
this._repeatControls[i].moveRepeatItemUpImage.setOpacity(i == 0 ? .3 : 1);
+ this._repeatControls[i].moveRepeatItemUpImage.tabIndex = (0 == i) ? (-1) : (0);
+ this._repeatControls[i].moveRepeatItemUpImage.alt = labelPrefix + alfresco.resources["move_up_title"];
+
this._repeatControls[i].moveRepeatItemDownImage.setOpacity(i == this._repeatControls.length - 1 ? .3 : 1);
+ this._repeatControls[i].moveRepeatItemDownImage.tabIndex = (i == (this._repeatControls.length - 1)) ? (-1) : (0);
+ this._repeatControls[i].moveRepeatItemDownImage.alt = labelPrefix + alfresco.resources["move_down_title"];
+
this._repeatControls[i].insertRepeatItemImage.setOpacity(insertEnabled ? 1 : .3);
+ this._repeatControls[i].insertRepeatItemImage.tabIndex = (insertEnabled) ? (0) : (-1);
+ this._repeatControls[i].insertRepeatItemImage.alt = labelPrefix + alfresco.resources["add_item_title"];
+
this._repeatControls[i].removeRepeatItemImage.setOpacity(removeEnabled ? 1 : .3);
+ this._repeatControls[i].removeRepeatItemImage.tabIndex = (removeEnabled) ? (0) : (-1);
+ this._repeatControls[i].removeRepeatItemImage.alt = labelPrefix + alfresco.resources["remove_item_title"];
}
},
@@ -3615,12 +3939,14 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
_insertChildAt: function(child, position)
{
this._repeatControls.splice(position, 0, new Element("div"));
+ var label = this.parentWidget.getLabel(); // this.getLabel() breaks dynamic dispatching mechanism of mootools for _insertChildAt()!
+ var labelPrefix = ((null != label) ? (label + " ") : ("")) + "Item " + (position + 1) + ". ";
var images =
[
- { name: "insertRepeatItemImage", src: "plus", action: this._insertRepeatItemAfter_handler },
- { name: "moveRepeatItemUpImage", src: "arrow_up", action: this._moveRepeatItemUp_handler },
- { name: "moveRepeatItemDownImage", src: "arrow_down", action: this._moveRepeatItemDown_handler },
- { name: "removeRepeatItemImage", src: "minus", action: this._removeRepeatItem_handler }
+ { name: "insertRepeatItemImage", src: "plus", action: this._insertRepeatItemAfter_handler, accessibilityAction: this._insertRepeatItemAfter_keypressHandler, title: alfresco.resources["add_item_title"] },
+ { name: "moveRepeatItemUpImage", src: "arrow_up", action: this._moveRepeatItemUp_handler, accessibilityAction: this._moveRepeatItemUp_keypressHandler, title: alfresco.resources["move_up_title"] },
+ { name: "moveRepeatItemDownImage", src: "arrow_down", action: this._moveRepeatItemDown_handler, accessibilityAction: this._moveRepeatItemDown_keypressHandler, title: alfresco.resources["move_down_title"] },
+ { name: "removeRepeatItemImage", src: "minus", action: this._removeRepeatItem_handler, accessibilityAction: this._removeRepeatItem_keypressHandler, title: alfresco.resources["remove_item_title"] }
];
var _repeatControlsWidth = 0;
for (var i = 0; i < images.length; i++)
@@ -3629,7 +3955,9 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
{
"src": (alfresco.constants.WEBAPP_CONTEXT + "/images/icons/" +
images[i].src + ".gif"),
- "styles": { "width" : "16px", "height" : "16px" }
+ "styles": { "width" : "16px", "height" : "16px" },
+ "alt": (labelPrefix + images[i].title),
+ "title": images[i].title
});
this._repeatControls[position][images[i].name] = img;
var imgMargin = [2, 5, 2, (i == 0 ? 5 : 0) ];
@@ -3637,6 +3965,7 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
_repeatControlsWidth += (parseInt(img.style.width) + imgMargin[1] + imgMargin[3]);
this._repeatControls[position].appendChild(img);
img.onclick = images[i].action.bindAsEventListener(this);
+ img.onkeypress = images[i].accessibilityAction.bindAsEventListener(this);
}
var result = this.parent(child, position);
@@ -3691,6 +4020,7 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
_childAdded: function(child)
{
this.headerInsertRepeatItemImage.setOpacity(.3);
+ this.headerInsertRepeatItemImage.tabIndex = -1;
this._updateRepeatControls();
},
@@ -3700,6 +4030,7 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
if (this._children.length == 0)
{
this.headerInsertRepeatItemImage.setOpacity(1);
+ this.headerInsertRepeatItemImage.tabIndex = 0;
}
this._updateRepeatControls();
},
@@ -3726,13 +4057,22 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
event.currentTarget.repeat.setFocusedChild(null);
}
};
-
+
+ var imageTitle = "";
+ if ((null != this.getLabel()) && (this.getLabel().length > 0))
+ {
+ imageTitle = this.getLabel() + " ";
+ }
+ imageTitle += alfresco.resources["add_item_title"];
+
this.headerInsertRepeatItemImage =
new Element("img",
{
"align": "absmiddle",
"src": alfresco.constants.WEBAPP_CONTEXT + "/images/icons/plus.gif",
- "styles": { "margin-left": "5px", "width": "16px", "height": "16px" }
+ "styles": { "margin-left": "5px", "width": "16px", "height": "16px" },
+ "title": alfresco.resources["add_item_title"],
+ "alt": imageTitle
});
this.headerInsertRepeatItemImage.repeat = this;
@@ -3740,6 +4080,7 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
this.headerInsertRepeatItemImage.onclick =
this._headerInsertRepeatItemBefore_handler.bindAsEventListener(this);
+ this.headerInsertRepeatItemImage.onkeypress = this._headerInsertRepeatItemBefore_keypressHandler.bindAsEventListener(this);
return this.domNode;
},
@@ -3807,6 +4148,14 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
}
},
+ _insertRepeatItemAfter_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._insertRepeatItemAfter_handler(event);
+ }
+ },
+
/**
* Event handler for insert before. If insert is enabled, causes a setRepeatIndeces
* and an insert.
@@ -3826,6 +4175,14 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
}
},
+ _headerInsertRepeatItemBefore_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._headerInsertRepeatItemBefore_handler(event);
+ }
+ },
+
/**
* Event handler for remove. If remove is enabled, causes a setRepeatIndeces
* and an delete.
@@ -3844,6 +4201,14 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
}
},
+ _removeRepeatItem_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._removeRepeatItem_handler(event);
+ }
+ },
+
/**
* Event handler for move up. Calls swap children with the child before
* if the current select child is not the first child.
@@ -3861,6 +4226,14 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
}
},
+ _moveRepeatItemUp_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._moveRepeatItemUp_handler(event);
+ }
+ },
+
/**
* Event handler for move down. Calls swap children with the child after
* if the current select child is not the last child.
@@ -3878,6 +4251,14 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
}
},
+ _moveRepeatItemDown_keypressHandler: function(event)
+ {
+ if ((null != event) && ((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))))
+ {
+ this._moveRepeatItemDown_handler(event);
+ }
+ },
+
/////////////////////////////////////////////////////////////////
// XForms event handlers
/////////////////////////////////////////////////////////////////
@@ -4492,6 +4873,8 @@ alfresco.xforms.XForm = new Class({
this._handleEventLog.bindAsEventListener(this));
},
+ _previousInvalidWidgets: null,
+
/** Handles the xforms event log resulting from a call to the XFormsBean. */
_handleEventLog: function(events)
{
@@ -4715,15 +5098,23 @@ alfresco.xforms.XForm = new Class({
{
this.submitWidget = null;
var invalid_widgets = this.rootWidget.getWidgetsInvalidForSubmit();
- _show_error(document.createTextNode(alfresco.resources["validation_provide_values_for_required_fields"]));
+ _show_error(document.createTextNode(alfresco.resources["validation_provide_values_for_required_fields"]), invalid_widgets.length);
var error_list = document.createElement("ul");
+
+ _removeAccessibilityErrorNotification(this._previousInvalidWidgets);
+ var strongTabIndex = 2;
invalid_widgets.each(function(invalid)
{
var error_item = document.createElement("li");
+ error_item.id = invalid.domNode.id + "-alertItem";
error_item.appendChild(document.createTextNode(invalid.getAlert()));
error_list.appendChild(error_item);
+ _applyAccessibilityErrorNotification(invalid, strongTabIndex++, error_item.id);
invalid.showAlert();
});
+
+ this._previousInvalidWidgets = invalid_widgets;
+
_show_error(error_list);
break;
}
@@ -4764,10 +5155,18 @@ function _hide_errors()
errorDiv.empty();
errorDiv.style.display = "none";
}
+
+ var errorLink = $("errorLink-with-key-v");
+ if (null != errorLink)
+ {
+ errorLink.tabIndex = -1;
+ errorLink.parentNode.removeChild(errorLink);
+ errorLink = null;
+ }
}
/** shows the error message display. */
-function _show_error(msg)
+function _show_error(msg, errorCount)
{
var errorDiv = $(alfresco.xforms.constants.XFORMS_ERROR_DIV_ID);
if (!errorDiv)
@@ -4777,6 +5176,44 @@ function _show_error(msg)
errorDiv.injectBefore($(alfresco.xforms.constants.XFORMS_UI_DIV_ID));
}
+ var errorLink = $("errorLink-with-key-v");
+ if (null == errorLink)
+ {
+ errorLink = new Element("a",
+ {
+ "id": "errorLink-with-key-v",
+ "src": "javascript: ;",
+ "accessKey": "v",
+ "role": "alert",
+ "tabIndex": 1
+ });
+ errorLink.onclick = "return false;"
+ errorLink.onmousedown = "return false;"
+
+ var errorMessage = new Element("div",
+ {
+ "id": "accessibility-error-message"
+ });
+
+ if (null != errorCount)
+ {
+ errorMessage.appendChild(document.createTextNode(errorCount + " " + alfresco.resources["accessibility_validation_message_with_error_count"]));
+ }
+ else
+ {
+ errorMessage.appendChild(document.createTextNode(alfresco.resources["accessibility_validation_message"]));
+ }
+
+ errorLink.appendChild(errorMessage);
+ errorLink.injectBefore($(alfresco.xforms.constants.XFORMS_ERROR_DIV_ID));
+
+ errorMessage.style.width = "1px";
+ errorMessage.style.height = "1px";
+ errorMessage.style.filter = "alpha(opacity=0.01)";
+ errorMessage.style.color = "transparent";
+ errorMessage.style.overflow = "hidden";
+ }
+
if (errorDiv.style.display == "block")
{
errorDiv.appendChild(document.createElement("br"));
@@ -4786,6 +5223,194 @@ function _show_error(msg)
errorDiv.style.display = "block";
}
errorDiv.appendChild(msg);
+
+ errorLink.focus();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Accessibility helpers related to the fields validation
+////////////////////////////////////////////////////////////////////////////////
+
+function _getDateTimePickerLabels(parent)
+{
+ return [
+ {
+ "tagName": "div",
+ "id": "increase-week-label",
+ "style": "width: 1px; height: 1px; filter: alpha(opacity=0.01); color: transparent; overflow: hidden",
+ "parent": parent,
+ "text": alfresco.resources["increase_week_label"]
+ },
+ {
+ "tagName": "div",
+ "id": "increase-month-label",
+ "style": "width: 1px; height: 1px; filter: alpha(opacity=0.01); color: transparent; overflow: hidden",
+ "parent": parent,
+ "text": alfresco.resources["increase_month_label"]
+ },
+ {
+ "tagName": "div",
+ "id": "decrease-week-label",
+ "style": "width: 1px; height: 1px; filter: alpha(opacity=0.01); color: transparent; overflow: hidden",
+ "parent": parent,
+ "text": alfresco.resources["decrease_week_label"]
+ },
+ {
+ "tagName": "div",
+ "id": "decrease-month-label",
+ "style": "width: 1px; height: 1px; filter: alpha(opacity=0.01); color: transparent; overflow: hidden",
+ "parent": parent,
+ "text": alfresco.resources["decrease_month_label"]
+ }
+ ];
+}
+
+function _createExternalLabels(labelIds)
+{
+ if ((null == labelIds) || (null == labelIds.length) || (0 == labelIds.length))
+ {
+ return;
+ }
+
+ for (var i = 0; i < labelIds.length; i++)
+ {
+ var el = labelIds[i];
+ if (null == document.getElementById(el.id))
+ {
+ var label = new Element(el.tagName,
+ {
+ "id": el.id,
+ "style": el.style
+ });
+
+ if (null != el.parent)
+ {
+ el.parent.appendChild(label);
+ }
+ else
+ {
+ document.appendChild(label);
+ }
+
+ label.appendChild(document.createTextNode(el.text));
+ }
+ }
+}
+
+function _removeAccessibilityErrorNotification(widgets)
+{
+ if (null != widgets)
+ {
+ widgets.each(function(invalid)
+ {
+ _applyAccessibilityErrorNotification(invalid, 0, null);
+ });
+ }
+}
+
+function _applyAccessibilityErrorNotification(field, tabIndex, alertId)
+{
+ if ((null == field) || (null == tabIndex))
+ {
+ return;
+ }
+
+ var control = _findFirstControl(field.domNode);
+
+ if (null != control)
+ {
+ control.tabIndex = tabIndex;
+
+ if (null == alertId)
+ {
+ control.removeAttribute("aria-labelledby");
+ }
+ else
+ {
+ control.setAttribute("aria-labelledby", alertId);
+ }
+
+ if ((tabIndex > 0) && (null == control.getAttribute("role")))
+ {
+ switch (control.tagName)
+ {
+ case "SELECT":
+ {
+ control.setAttribute("role", ((control.multiple) ? ("listbox") : ("combobox")));
+ break;
+ }
+ case "A":
+ {
+ control.setAttribute("role", "link");
+ break;
+ }
+ case "TEXTAREA": case "DIV":
+ {
+ control.setAttribute("role", "textbox");
+ control.setAttribute("aria-multiline", true);
+ break;
+ }
+ case "INPUT":
+ {
+ switch (control.type)
+ {
+ case "button": case "checkbox": case "radio":
+ {
+ control.setAttribute("role", control.type);
+ break;
+ }
+ case "hidden": case "password": case "text":
+ {
+ control.setAttribute("role", "textbox");
+ break;
+ }
+ case "submit": case "reset":
+ {
+ control.setAttribute("role", "button");
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (0 == tabIndex)
+ {
+ control.removeAttribute("role");
+ }
+ }
+ }
+}
+
+function _findFirstControl(element)
+{
+ if (null == element)
+ {
+ return null;
+ }
+
+ if (("INPUT" == element.tagName) || ("SELECT" == element.tagName) || ("TEXTAREA" == element.tagName) || ((null != element.id) && (0 == element.id.toLowerCase().indexOf("textarea"))))
+ {
+ if (("DIV" == element.tagName) && (null != element.parentNode.children) && (0 != element.parentNode.children.length) && ("A" == element.parentNode.children[0].tagName))
+ {
+ return element.parentNode.children[0];
+ }
+ return element;
+ }
+
+ if (null != element.children)
+ {
+ for (var i = 0; i < element.children.length; i++)
+ {
+ var result = _findFirstControl(element.children[i]);
+ if (null != result)
+ {
+ return result;
+ }
+ }
+ }
+
+ return null;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/source/web/scripts/tiny_mce/classes/ui/Button.js b/source/web/scripts/tiny_mce/classes/ui/Button.js
index f683114443..2bee37c64f 100644
--- a/source/web/scripts/tiny_mce/classes/ui/Button.js
+++ b/source/web/scripts/tiny_mce/classes/ui/Button.js
@@ -45,7 +45,7 @@
if (s.image)
h += ' ' + l + '';
else
- h += '' + (l ? '' + l + '' : '') + '';
+ h += '' + s.title + ' ' + (l ? '' + l + '' : '') + '';
return h;
},
diff --git a/source/web/scripts/tiny_mce/classes/ui/SplitButton.js b/source/web/scripts/tiny_mce/classes/ui/SplitButton.js
index b2fa481430..dca72e4870 100644
--- a/source/web/scripts/tiny_mce/classes/ui/SplitButton.js
+++ b/source/web/scripts/tiny_mce/classes/ui/SplitButton.js
@@ -42,13 +42,22 @@
if (s.image)
h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});
- else
- h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');
+ else {
+ var titleDiv = DOM.createHTML("div", {
+ "style": "clear: none; width: 1px; height: 1px; filter: alpha(opacity=0.01); color: transparent; overflow: hidden;"
+ }, s.title);
+ h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, titleDiv);
+ }
h += ' | ' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ' | ';
h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});
- h += '' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ' | ';
+
+ var titleDiv = DOM.createHTML("div", {
+ "style": "clear: none; width: 1px; height: 1px; filter: alpha(opacity=0.01); color: transparent; overflow: hidden;"
+ }, h1);
+
+ h += '' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, titleDiv) + ' | ';
h += '';
diff --git a/source/web/scripts/tiny_mce/tiny_mce.js b/source/web/scripts/tiny_mce/tiny_mce.js
index 8c511f385b..f9a6011290 100644
--- a/source/web/scripts/tiny_mce/tiny_mce.js
+++ b/source/web/scripts/tiny_mce/tiny_mce.js
@@ -1 +1 @@
-var tinymce={majorVersion:"3",minorVersion:"2.7",releaseDate:"2009-09-22",_init:function(){var o=this,k=document,l=window,j=navigator,b=j.userAgent,h,a,g,f,e,m;o.isOpera=l.opera&&opera.buildNumber;o.isWebKit=/WebKit/.test(b);o.isIE=!o.isWebKit&&!o.isOpera&&(/MSIE/gi).test(b)&&(/Explorer/gi).test(j.appName);o.isIE6=o.isIE&&/MSIE [56]/.test(b);o.isGecko=!o.isWebKit&&/Gecko/.test(b);o.isMac=b.indexOf("Mac")!=-1;o.isAir=/adobeair/i.test(b);if(l.tinyMCEPreInit){o.suffix=tinyMCEPreInit.suffix;o.baseURL=tinyMCEPreInit.base;o.query=tinyMCEPreInit.query;return}o.suffix="";a=k.getElementsByTagName("base");for(h=0;h=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f==1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length==0||f[c]=="."){continue}if(f[c]==".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!=0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();tinymce.create("static tinymce.util.JSON",{serialize:function(e){var c,a,d=tinymce.util.JSON.serialize,b;if(e==null){return"null"}b=typeof e;if(b=="string"){a="\bb\tt\nn\ff\rr\"\"''\\\\";return'"'+e.replace(/([\u0080-\uFFFF\x00-\x1f\"])/g,function(g,f){c=a.indexOf(f);if(c+1){return"\\"+a.charAt(c+1)}g=f.charCodeAt().toString(16);return"\\u"+"0000".substring(g.length)+g})+'"'}if(b=="object"){if(e.hasOwnProperty&&e instanceof Array){for(c=0,a="[";c0?",":"")+d(e[c])}return a+"]"}a="{";for(c in e){a+=typeof e[c]!="function"?(a.length>1?',"':'"')+c+'":'+d(e[c]):""}return a+"}"}return""+e},parse:function(s){try{return eval("("+s+")")}catch(ex){}}});tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){e.call(f.error_scope||f.scope,h,g)};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(c){var e=c.each,b=c.is;var d=c.isWebKit,a=c.isIE;c.create("tinymce.dom.DOMUtils",{doc:null,root:null,files:null,pixelStyles:/^(top|left|bottom|right|width|height|borderWidth)$/,props:{"for":"htmlFor","class":"className",className:"className",checked:"checked",disabled:"disabled",maxlength:"maxLength",readonly:"readOnly",selected:"selected",value:"value",id:"id",name:"name",type:"type"},DOMUtils:function(i,g){var f=this;f.doc=i;f.win=window;f.files={};f.cssFlicker=false;f.counter=0;f.boxModel=!c.isIE||i.compatMode=="CSS1Compat";f.stdMode=i.documentMode===8;f.settings=g=c.extend({keep_values:false,hex_colors:1,process_html:1},g);if(c.isIE6){try{i.execCommand("BackgroundImageCache",false,true)}catch(h){f.cssFlicker=true}}c.addUnload(f.destroy,f)},getRoot:function(){var f=this,g=f.settings;return(g&&f.get(g.root_element))||f.doc.body},getViewPort:function(g){var h,f;g=!g?this.win:g;h=g.document;f=this.boxModel?h.documentElement:h.body;return{x:g.pageXOffset||f.scrollLeft,y:g.pageYOffset||f.scrollTop,w:g.innerWidth||f.clientWidth,h:g.innerHeight||f.clientHeight}},getRect:function(i){var h,f=this,g;i=f.get(i);h=f.getPos(i);g=f.getSize(i);return{x:h.x,y:h.y,w:g.w,h:g.h}},getSize:function(j){var g=this,f,i;j=g.get(j);f=g.getStyle(j,"width");i=g.getStyle(j,"height");if(f.indexOf("px")===-1){f=0}if(i.indexOf("px")===-1){i=0}return{w:parseInt(f)||j.offsetWidth||j.clientWidth,h:parseInt(i)||j.offsetHeight||j.clientHeight}},getParent:function(i,h,g){return this.getParents(i,h,g,false)},getParents:function(p,k,i,m){var h=this,g,j=h.settings,l=[];p=h.get(p);m=m===undefined;if(j.strict_root){i=i||h.getRoot()}if(b(k,"string")){g=k;if(k==="*"){k=function(f){return f.nodeType==1}}else{k=function(f){return h.is(f,g)}}}while(p){if(p==i||!p.nodeType||p.nodeType===9){break}if(!k||k(p)){if(m){l.push(p)}else{return p}}p=p.parentNode}return m?l:null},get:function(f){var g;if(f&&this.doc&&typeof(f)=="string"){g=f;f=this.doc.getElementById(f);if(f&&f.id!==g){return this.doc.getElementsByName(g)[1]}}return f},getNext:function(g,f){return this._findSib(g,f,"nextSibling")},getPrev:function(g,f){return this._findSib(g,f,"previousSibling")},select:function(h,g){var f=this;return c.dom.Sizzle(h,f.get(g)||f.get(f.settings.root_element)||f.doc,[])},is:function(g,f){return c.dom.Sizzle.matches(f,g.nodeType?[g]:g).length>0},add:function(j,l,f,i,k){var g=this;return this.run(j,function(n){var m,h;m=b(l,"string")?g.doc.createElement(l):l;g.setAttribs(m,f);if(i){if(i.nodeType){m.appendChild(i)}else{g.setHTML(m,i)}}return !k?n.appendChild(m):m})},create:function(i,f,g){return this.add(this.doc.createElement(i),i,f,g,1)},createHTML:function(m,f,j){var l="",i=this,g;l+="<"+m;for(g in f){if(f.hasOwnProperty(g)){l+=" "+g+'="'+i.encode(f[g])+'"'}}if(c.is(j)){return l+">"+j+""+m+">"}return l+" />"},remove:function(h,f){var g=this;return this.run(h,function(m){var l,k,j;l=m.parentNode;if(!l){return null}if(f){for(j=m.childNodes.length-1;j>=0;j--){g.insertAfter(m.childNodes[j],m)}}if(g.fixPsuedoLeaks){l=m.cloneNode(true);f="IELeakGarbageBin";k=g.get(f)||g.add(g.doc.body,"div",{id:f,style:"display:none"});k.appendChild(m);k.innerHTML="";return l}return l.removeChild(m)})},setStyle:function(i,f,g){var h=this;return h.run(i,function(l){var k,j;k=l.style;f=f.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(h.pixelStyles.test(f)&&(c.is(g,"number")||/^[\-0-9\.]+$/.test(g))){g+="px"}switch(f){case"opacity":if(a){k.filter=g===""?"":"alpha(opacity="+(g*100)+")";if(!i.currentStyle||!i.currentStyle.hasLayout){k.display="inline-block"}}k[f]=k["-moz-opacity"]=k["-khtml-opacity"]=g||"";break;case"float":a?k.styleFloat=g:k.cssFloat=g;break;default:k[f]=g||""}if(h.settings.update_styles){h.setAttrib(l,"mce_style")}})},getStyle:function(i,f,h){i=this.get(i);if(!i){return false}if(this.doc.defaultView&&h){f=f.replace(/[A-Z]/g,function(j){return"-"+j});try{return this.doc.defaultView.getComputedStyle(i,null).getPropertyValue(f)}catch(g){return null}}f=f.replace(/-(\D)/g,function(k,j){return j.toUpperCase()});if(f=="float"){f=a?"styleFloat":"cssFloat"}if(i.currentStyle&&h){return i.currentStyle[f]}return i.style[f]},setStyles:function(i,j){var g=this,h=g.settings,f;f=h.update_styles;h.update_styles=0;e(j,function(k,l){g.setStyle(i,l,k)});h.update_styles=f;if(h.update_styles){g.setAttrib(i,h.cssText)}},setAttrib:function(h,i,f){var g=this;if(!h||!i){return}if(g.settings.strict){i=i.toLowerCase()}return this.run(h,function(k){var j=g.settings;switch(i){case"style":if(!b(f,"string")){e(f,function(l,m){g.setStyle(k,m,l)});return}if(j.keep_values){if(f&&!g._isRes(f)){k.setAttribute("mce_style",f,2)}else{k.removeAttribute("mce_style",2)}}k.style.cssText=f;break;case"class":k.className=f||"";break;case"src":case"href":if(j.keep_values){if(j.url_converter){f=j.url_converter.call(j.url_converter_scope||g,f,i,k)}g.setAttrib(k,"mce_"+i,f,2)}break;case"shape":k.setAttribute("mce_style",f);break}if(b(f)&&f!==null&&f.length!==0){k.setAttribute(i,""+f,2)}else{k.removeAttribute(i,2)}})},setAttribs:function(g,h){var f=this;return this.run(g,function(i){e(h,function(j,k){f.setAttrib(i,k,j)})})},getAttrib:function(i,j,h){var f,g=this;i=g.get(i);if(!i||i.nodeType!==1){return false}if(!b(h)){h=""}if(/^(src|href|style|coords|shape)$/.test(j)){f=i.getAttribute("mce_"+j);if(f){return f}}if(a&&g.props[j]){f=i[g.props[j]];f=f&&f.nodeValue?f.nodeValue:f}if(!f){f=i.getAttribute(j,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(j)){if(i[g.props[j]]===true&&f===""){return j}return f?j:""}if(i.nodeName==="FORM"&&i.getAttributeNode(j)){return i.getAttributeNode(j).nodeValue}if(j==="style"){f=f||i.style.cssText;if(f){f=g.serializeStyle(g.parseStyle(f));if(g.settings.keep_values&&!g._isRes(f)){i.setAttribute("mce_style",f)}}}if(d&&j==="class"&&f){f=f.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(a){switch(j){case"rowspan":case"colspan":if(f===1){f=""}break;case"size":if(f==="+0"||f===20||f===0){f=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(f===0){f=""}break;case"hspace":if(f===-1){f=""}break;case"maxlength":case"tabindex":if(f===32768||f===2147483647||f==="32768"){f=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(f===65535){return j}return h;case"shape":f=f.toLowerCase();break;default:if(j.indexOf("on")===0&&f){f=(""+f).replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1")}}}return(f!==undefined&&f!==null&&f!=="")?""+f:h},getPos:function(m,i){var g=this,f=0,l=0,j,k=g.doc,h;m=g.get(m);i=i||k.body;if(m){if(a&&!g.stdMode){m=m.getBoundingClientRect();j=g.boxModel?k.documentElement:k.body;f=g.getStyle(g.select("html")[0],"borderWidth");f=(f=="medium"||g.boxModel&&!g.isIE6)&&2||f;m.top+=g.win.self!=g.win.top?2:0;return{x:m.left+j.scrollLeft-f,y:m.top+j.scrollTop-f}}h=m;while(h&&h!=i&&h.nodeType){f+=h.offsetLeft||0;l+=h.offsetTop||0;h=h.offsetParent}h=m.parentNode;while(h&&h!=i&&h.nodeType){f-=h.scrollLeft||0;l-=h.scrollTop||0;h=h.parentNode}}return{x:f,y:l}},parseStyle:function(h){var i=this,j=i.settings,k={};if(!h){return k}function f(w,q,v){var o,u,m,n;o=k[w+"-top"+q];if(!o){return}u=k[w+"-right"+q];if(o!=u){return}m=k[w+"-bottom"+q];if(u!=m){return}n=k[w+"-left"+q];if(m!=n){return}k[v]=n;delete k[w+"-top"+q];delete k[w+"-right"+q];delete k[w+"-bottom"+q];delete k[w+"-left"+q]}function g(n,m,l,p){var o;o=k[m];if(!o){return}o=k[l];if(!o){return}o=k[p];if(!o){return}k[n]=k[m]+" "+k[l]+" "+k[p];delete k[m];delete k[l];delete k[p]}h=h.replace(/&(#?[a-z0-9]+);/g,"&$1_MCE_SEMI_");e(h.split(";"),function(m){var l,n=[];if(m){m=m.replace(/_MCE_SEMI_/g,";");m=m.replace(/url\([^\)]+\)/g,function(o){n.push(o);return"url("+n.length+")"});m=m.split(":");l=c.trim(m[1]);l=l.replace(/url\(([^\)]+)\)/g,function(p,o){return n[parseInt(o)-1]});l=l.replace(/rgb\([^\)]+\)/g,function(o){return i.toHex(o)});if(j.url_converter){l=l.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g,function(o,p){return"url("+j.url_converter.call(j.url_converter_scope||i,i.decode(p),"style",null)+")"})}k[c.trim(m[0]).toLowerCase()]=l}});f("border","","border");f("border","-width","border-width");f("border","-color","border-color");f("border","-style","border-style");f("padding","","padding");f("margin","","margin");g("border","border-width","border-style","border-color");if(a){if(k.border=="medium none"){k.border=""}}return k},serializeStyle:function(g){var f="";e(g,function(i,h){if(h&&i){if(c.isGecko&&h.indexOf("-moz-")===0){return}switch(h){case"color":case"background-color":i=i.toLowerCase();break}f+=(f?" ":"")+h+": "+i+";"}});return f},loadCSS:function(f){var h=this,i=h.doc,g;if(!f){f=""}g=h.select("head")[0];e(f.split(","),function(j){var k;if(h.files[j]){return}h.files[j]=true;k=h.create("link",{rel:"stylesheet",href:c._addVer(j)});if(a&&i.documentMode){k.onload=function(){i.recalc();k.onload=null}}g.appendChild(k)})},addClass:function(f,g){return this.run(f,function(h){var i;if(!g){return 0}if(this.hasClass(h,g)){return h.className}i=this.removeClass(h,g);return h.className=(i!=""?(i+" "):"")+g})},removeClass:function(h,i){var f=this,g;return f.run(h,function(k){var j;if(f.hasClass(k,i)){if(!g){g=new RegExp("(^|\\s+)"+i+"(\\s+|$)","g")}j=k.className.replace(g," ");return k.className=c.trim(j!=" "?j:"")}return k.className})},hasClass:function(g,f){g=this.get(g);if(!g||!f){return false}return(" "+g.className+" ").indexOf(" "+f+" ")!==-1},show:function(f){return this.setStyle(f,"display","block")},hide:function(f){return this.setStyle(f,"display","none")},isHidden:function(f){f=this.get(f);return !f||f.style.display=="none"||this.getStyle(f,"display")=="none"},uniqueId:function(f){return(!f?"mce_":f)+(this.counter++)},setHTML:function(i,g){var f=this;return this.run(i,function(m){var h,k,j,q,l,h;g=f.processHTML(g);if(a){function o(){try{m.innerHTML=" "+g;m.removeChild(m.firstChild)}catch(n){while(m.firstChild){m.firstChild.removeNode()}h=f.create("div");h.innerHTML=" "+g;e(h.childNodes,function(r,p){if(p){m.appendChild(r)}})}}if(f.settings.fix_ie_paragraphs){g=g.replace(/<\/p>| ]+)><\/p>| /gi,' ')}o();if(f.settings.fix_ie_paragraphs){j=m.getElementsByTagName("p");for(k=j.length-1,h=0;k>=0;k--){q=j[k];if(!q.hasChildNodes()){if(!q.mce_keep){h=1;break}q.removeAttribute("mce_keep")}}}if(h){g=g.replace(/]+)>| /ig,' ');g=g.replace(/<\/p>/g," ");o();if(f.settings.fix_ie_paragraphs){j=m.getElementsByTagName("DIV");for(k=j.length-1;k>=0;k--){q=j[k];if(q.mce_tmp){l=f.doc.createElement("p");q.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi,function(p,n){var r;if(n!=="mce_tmp"){r=q.getAttribute(n);if(!r&&n==="class"){r=q.className}l.setAttribute(n,r)}});for(h=0;h|]+)>/gi,"<$1b$2>");j=j.replace(/<(\/?)em>|]+)>/gi,"<$1i$2>")}else{if(a){j=j.replace(/'/g,"'");j=j.replace(/\s+(disabled|checked|readonly|selected)\s*=\s*[\"\']?(false|0)[\"\']?/gi,"")}}j=j.replace(/]+)\/>|/gi,"");if(i.keep_values){if(/ |